/*
 * Fiyobra accessibility layer (roadmap Phase 9).
 *
 * Loaded LAST, after fiyobra-brand.css, so these rules win over both the Toner
 * theme and the brand retone.
 *
 * A separate file on purpose. Every block below exists to satisfy a specific
 * WCAG 2.2 AA success criterion and names it, so a future restyle can tell
 * "this is a design choice" apart from "this is a conformance requirement".
 * Colour-token contrast fixes are NOT here — those had to change at source, in
 * fiyobra-brand.css, or every component that reads the token would still be
 * failing.
 *
 * See docs/accessibility-audit.md for what was found and docs/accessibility.md
 * for what is claimed.
 */

/* ── 2.4.1 Bypass Blocks ───────────────────────────────────────────────────
 * Off-screen until focused rather than display:none — a hidden element is not
 * focusable, so a skip link that appears on :focus has to still be in the
 * layout while it is invisible.
 *
 * translateY and not `left: -9999px`: off-canvas horizontally makes some
 * browsers scroll the page sideways when the link takes focus.
 */
.fi-skip-link {
  position: absolute;
  top: 0;
  left: 0;
  z-index: 2000;
  padding: 0.75rem 1.25rem;
  background: var(--fi-rose);
  color: #ffffff;
  font-weight: 500;
  text-decoration: none;
  border-bottom-right-radius: 12px;
  transform: translateY(-120%);
  transition: transform 0.15s ease;
}

.fi-skip-link:focus,
.fi-skip-link:focus-visible {
  transform: translateY(0);
  color: #ffffff;
  outline: 3px solid var(--fi-focus-ring, #1a1a1a);
  outline-offset: 2px;
}

/* The skip-link destination. tabindex="-1" makes <main> focusable so the link
 * has somewhere to land; the ring browsers then paint on it means nothing to a
 * sighted user, because <main> is not an interactive control. */
main:focus,
main:focus-visible {
  outline: none;
}

/* ── 2.4.7 Focus Visible, 1.4.11 Non-text Contrast ─────────────────────────
 * One visible indicator for every interactive element, via :focus-visible so a
 * mouse click does not leave a ring behind. The theme paints over Bootstrap's
 * own ring in several places (.fi-search, the admin nav, the category rail,
 * the hero dots) and the custom controls this app adds never had one.
 *
 * 3px of near-black clears the 3:1 that 1.4.11 asks of a focus indicator
 * against every background in this palette. A rose ring would not — it is the
 * accent, so it lands on rose surfaces.
 */
/* Explicit type selectors rather than :where(), and this is not a style
 * preference: the Toner theme ships `a:focus{outline:0}`, which at specificity
 * (0,1,1) beat a :where() rule at (0,1,0) and left every link in the footer
 * with no visible focus at all. Matching that specificity and loading later is
 * what wins the tie. Found by the axe-core suite, not by the manual audit. */
a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
summary:focus-visible,
[tabindex]:focus-visible {
  /* !important, reluctantly and deliberately. The Toner theme shipped
   * `a, button { outline: 0 !important }`, which suppressed the focus ring on
   * every link and button in the application no matter what specificity we
   * wrote. That declaration has been removed from the copied asset, but the
   * assets under public/assets are a VENDOR COPY — re-copying the theme would
   * bring it straight back, and silently. This is the belt to that braces. */
  /* The colour is a token since redesign Phase A: near-black on the Noir page
   * is invisible, so fiyobra-noir.css sets --fi-focus-ring per theme (ink on
   * dark, near-black on light). The fallback keeps this rule self-sufficient
   * if that file is ever missing; the !important stays for the reason above. */
  outline: 3px solid var(--fi-focus-ring, #1a1a1a) !important;
  outline-offset: 2px;
}

/* Controls that sit ON the accent get the inverse, or the ring disappears into
 * the button it is outlining. */
.btn-primary:focus-visible,
.fi-hero .btn-light:focus-visible,
.fi-admin-nav-link.active:focus-visible {
  outline-color: #ffffff;
  box-shadow: 0 0 0 5px var(--fi-focus-halo, rgba(26, 26, 26, 0.55));
}

/* The search field substitutes a shadow for the outline, so it keeps a ring
 * that follows its pill shape rather than the square default. */
.fi-search input:focus-visible {
  outline: 3px solid var(--fi-focus-ring, #1a1a1a);
  outline-offset: 2px;
  border-radius: 999px;
}

/* ── 1.4.1 Use of Colour ───────────────────────────────────────────────────
 * Toggle buttons and nav items that were distinguished by fill alone.
 * aria-pressed / aria-current is the programmatic half of the fix; this is the
 * visible half, for someone who can see the control but cannot reliably tell
 * two mid-tones apart.
 */
[aria-pressed='true'],
[aria-current='page'],
[aria-current='true'] {
  font-weight: 600;
}

.btn[aria-pressed='true']::before,
.fi-admin-nav-link[aria-current='page']::before {
  content: '';
  display: inline-block;
  width: 0.5rem;
  height: 0.5rem;
  margin-right: 0.4rem;
  border-radius: 50%;
  background: currentColor;
}

/* ── 1.4.3 Contrast — ratings and the "featured" star ──────────────────────
 * Bootstrap's .text-warning (#ffc107) is 1.63:1 on white. A rating is
 * information, not decoration, so it has to be legible — and an empty star has
 * to be distinguishable from a filled one by more than saturation.
 */
.fi-rating {
  color: #8a6100; /* 4.94:1 on #ffffff */
}

.fi-rating .fi-rating-empty {
  color: #767676; /* 4.54:1 on #ffffff */
}

.fi-featured-icon {
  color: #8a6100;
}

/* ── 2.5.8 Target Size (Minimum) ───────────────────────────────────────────
 * 24x24 CSS px is the AA floor, and the icon-only row actions in the admin
 * tables were under it once Bootstrap's small-button padding was applied.
 * 36px is comfortably clear and matches the height of a .btn-sm with text.
 */
.fi-icon-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 2.25rem;
  min-height: 2.25rem;
}

/* ── 4.1.3 Status Messages ─────────────────────────────────────────────────
 * A live region has to exist in the DOM before its content changes, so these
 * are always rendered and empty until something happens.
 *
 * The clip technique, not display:none — the latter removes the element from
 * the accessibility tree, taking the announcement with it.
 */
.fi-visually-hidden,
.fi-live-region {
  position: absolute !important;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* Visible again when focused, for a "skip"-style control that is hidden until
 * a keyboard user reaches it. */
.fi-visually-hidden-focusable:not(:focus):not(:focus-within) {
  position: absolute !important;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
}

/* ── 3.3.1 Error Identification — the summary above a failed form ──────────*/
.fi-error-summary {
  border: 2px solid #b02a37;
  border-radius: 12px;
  padding: 1rem 1.25rem;
  margin-bottom: 1.25rem;
  background: var(--fi-card, #ffffff);
}

.fi-error-summary ul {
  margin: 0.5rem 0 0;
  padding-left: 1.25rem;
}

/* Each entry is a link to the field that failed, and they were stacked tightly
 * enough that a 24px target circle overlapped its neighbour (WCAG 2.5.8). The
 * links themselves are inline text, so the fix is the spacing between rows
 * rather than the size of the link. */
.fi-error-summary li {
  line-height: 1.7;
  padding: 0.15rem 0;
}

/* ── 1.3.1 Info and Relationships — fieldsets that must not look like one ──
 * Several groups became <fieldset>/<legend> for the semantics. Bootstrap does
 * not style either, but browsers give a fieldset a default border and a legend
 * its own font sizing, which would change the visual design.
 */
.fi-fieldset {
  border: 0;
  padding: 0;
  margin: 0;
  min-width: 0; /* Chrome gives fieldsets min-content sizing; this reflows. */
}

.fi-fieldset > legend {
  float: none;
  width: auto;
  padding: 0;
  font-size: inherit;
  line-height: inherit;
}

/* ── 2.3.3 Animation from Interactions / 2.2.2 Pause, Stop, Hide ───────────
 * "Reduce motion" is an accessibility setting, not a performance one: for some
 * people vestibular motion is nauseating, and for others a moving interface is
 * simply unusable.
 *
 * Durations are collapsed rather than removed — 0.01ms still fires
 * transitionend, so anything in JS awaiting one does not hang forever.
 *
 * The home hero's auto-rotation is also stopped in JS (see
 * resources/js/Pages/Site/Home.jsx). CSS cannot pause a setInterval, and a
 * carousel that keeps swapping the page's <h1> is the 2.2.2 failure this phase
 * found.
 */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }

  /* Hover treatments that MOVE something. Colour changes stay: they are the
   * affordance, and they do not move. */
  .fi-card-hover:hover,
  .fi-product-card:hover,
  .fi-cat:hover .fi-cat-circle,
  .fi-product-card:hover .fi-product-media img {
    transform: none;
  }

  /* The admin drawer arrives in place instead of sliding in. */
  .fi-admin-sidebar {
    transition: none;
  }
}

/* ── 1.4.4 Resize Text / 1.4.10 Reflow ─────────────────────────────────────
 * The two places the theme fixes a width in a way that stops content
 * reflowing at 320 px. Everything else is Bootstrap's grid, which reflows.
 */
@media (max-width: 380px) {
  .fi-hero-figure {
    display: none;
  }

  .fi-seller-logo {
    width: 64px;
    height: 64px;
  }
}

/* ── 1.4.12 Text Spacing ───────────────────────────────────────────────────
 * The criterion fails on containers with a fixed height that clip enlarged
 * text. The only ones here were the eyebrow labels, which relied on a
 * line-height of 1 inside a flex row.
 */
.fi-eyebrow,
.fi-admin-section {
  line-height: 1.4;
}

/* ── Windows High Contrast (forced-colors) ─────────────────────────────────
 * The OS drops backgrounds and shadows in this mode, so anything whose meaning
 * was carried by a background colour needs a border to survive.
 */
@media (forced-colors: active) {
  .fi-admin-nav-link.active,
  .btn[aria-pressed='true'],
  .badge,
  .fi-discount-badge {
    border: 1px solid currentColor;
  }

  .fi-skip-link {
    border: 2px solid currentColor;
  }
}


/* ── 1.4.3 Contrast — the two Bootstrap utilities that failed ──────────────
 * Both found by axe-core against a rendered page, which is exactly the kind
 * of failure a manual read of the stylesheet misses: neither colour is
 * written down anywhere, both are computed from a token at paint time.
 */

/* `.text-muted` resolves to rgba(85,85,85,.75) over whatever is behind it —
 * about #7e7e7e on a white card, which is 4.36:1 and under the minimum for
 * the 14px text it is used on. A solid grey instead of a translucent one, so
 * the ratio does not depend on the background. */
:root {
  --tb-secondary-color: var(--fi-ink-2, #6b6b6b); /* 5.30:1 on #ffffff; per theme since Phase A */
  --bs-secondary-color: var(--fi-ink-2, #6b6b6b);
}

/* `.text-primary` is the rose accent, which is 4.87:1 on white — fine — but
 * it is also used as the FOREGROUND on `.bg-primary-subtle` (#fde4e9), where
 * it is 3.94:1. The darker rose already exists in the palette as the
 * "emphasis" tone and clears both. !important because Bootstrap's own colour
 * utilities carry it, so nothing else can win. */
.text-primary {
  /* --fi-accent-text is the per-theme text crimson (redesign Phase A). */
  color: var(--fi-accent-text, var(--fi-rose-active)) !important; /* 8.71:1 on white, 7.06:1 on #fde4e9 */
}

/* ── 2.5.8 Target Size (Minimum) — the hero's slide dots ───────────────────
 * They were 9x9. The painted dot stays that size; the BUTTON grows to 24x24
 * and clips its background to the content box, so the hit area meets the
 * minimum without the design changing.
 */
.fi-hero-dot {
  box-sizing: border-box;
  width: 24px;
  height: 24px;
  padding: 7px;
  background-clip: content-box;
  border-radius: 999px;
}

.fi-hero-dot.active {
  width: 40px;
}

/* The pause control sits in the same row and needs the same floor. */
.fi-hero-control {
  box-sizing: border-box;
  min-width: 24px;
  min-height: 24px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0 4px;
  border: 0;
  border-radius: 999px;
  background: var(--fi-elevated, rgba(255, 255, 255, 0.45));
  color: var(--fi-ink, #1a1a1a);
  cursor: pointer;
}

.fi-hero-control:hover {
  background: var(--fi-card-border, #ffffff);
}


/* ══════════════════════════════════════════════════════════════════════════
 * Found by axe-core, not by the manual audit
 *
 * Everything below is a real WCAG failure that reading the stylesheet could
 * not have caught, because none of these colours or sizes is written down —
 * they are computed at paint time from a Bootstrap token, an opacity, or a
 * font size. This is the argument for the automated suite existing at all.
 * ══════════════════════════════════════════════════════════════════════════ */

/* ── 2.5.8 Target Size — checkboxes and radios ─────────────────────────────
 * Bootstrap renders these at 1em, which is 16px. The rule's floor is 24, and
 * the "sufficient spacing" exemption does not apply to a stacked filter list
 * where the rows are 24px apart centre to centre.
 */
.form-check-input {
  width: 1.5em;
  height: 1.5em;
  margin-top: 0.05em;
}

.form-check {
  padding-left: 2em;
  min-height: 1.75em;
}

.form-check .form-check-input {
  margin-left: -2em;
}

.form-check-label {
  padding-top: 0.15em;
}

/* The switch variant is wider than it is tall, so only the height moves. */
.form-switch .form-check-input {
  width: 2.5em;
}

/* ── 1.4.3 Contrast — the "subtle" badge palettes ──────────────────────────
 * `.text-success` and `.text-danger` are readable on white and are used as the
 * FOREGROUND on `bg-*-subtle`, where they are not: #198754 on #d1e7dd is
 * 3.65:1 and #dc3545 on #f8d7da is 3.77:1. The emphasis tones clear both.
 */
.text-success {
  color: #0f5132 !important; /* 8.42:1 on #ffffff, 6.86:1 on #d1e7dd */
}

.text-danger {
  color: #b02a37 !important; /* 5.72:1 on #ffffff, 4.85:1 on #f8d7da */
}

.text-warning {
  color: #8a6100 !important; /* #ffc107 was 1.63:1 on white */
}

.text-info {
  color: #1a1a1a !important;
}

/* The alert bodies use the same family of tokens. */
.alert-warning {
  --tb-alert-color: #6c4a00;
  --bs-alert-color: #6c4a00;
}

/* ── 1.4.1 Use of Colour — links inside a block of text ────────────────────
 * A link in a paragraph that differs from the surrounding prose by colour
 * alone fails for anyone who cannot distinguish the two hues. Underlining is
 * the conventional non-colour cue, and it applies only where a link sits IN
 * text — navigation, buttons and cards are not text blocks and are not
 * underlined here.
 */
p a,
li a,
label a,
dd a,
figcaption a,
.fi-legal a,
.form-text a {
  text-decoration: underline;
}

/* …unless the author explicitly opted out AND the link is not in prose. Kept
 * narrow on purpose: `.text-decoration-none` inside a paragraph is exactly the
 * pattern that caused the failure, so it does not win there. */
p a.btn,
li a.btn,
li a.fi-chip,
li a.fi-tabbar-item,
li a.fi-rail-item,
.card-body > a.btn {
  text-decoration: none;
}


/* ── 1.4.3 Contrast — button variants ──────────────────────────────────────
 * Bootstrap's stock greys and greens, both under the minimum on white:
 *   .btn-outline-secondary  #6c757d text   4.02:1
 *   .btn-success            #ffffff on #198754  3.91:1
 * Darkened just enough to clear 4.5:1 while staying recognisably the same
 * button. Found by axe against the rendered dashboard.
 */
.btn-outline-secondary {
  --tb-btn-color: #565e64;
  --tb-btn-border-color: #6c757d;
  --tb-btn-hover-bg: #565e64;
  --tb-btn-hover-border-color: #565e64;
  --bs-btn-color: #565e64;
  --bs-btn-border-color: #6c757d;
}

.btn-success {
  --tb-btn-bg: #146c43;
  --tb-btn-border-color: #146c43;
  --tb-btn-hover-bg: #0f5132;
  --tb-btn-hover-border-color: #0f5132;
  --bs-btn-bg: #146c43;
  --bs-btn-border-color: #146c43;
}

/* ── 1.4.3 Contrast — the theme's semantic palette used as TEXT ────────────
 * The Toner tokens are chosen to be attractive as fills and are far too light
 * to read:
 *
 *   --tb-danger    #ef476f   3.50:1 on white
 *   --tb-success   #06d6a0   1.83:1
 *   --tb-warning   #f1be46   1.87:1
 *   --tb-info      #1ea6d3   2.71:1
 *   --tb-secondary #7c6bff   4.31:1
 *
 * That is fine where they are a background behind dark text, and a failure
 * everywhere they are the foreground — which is every outline button and every
 * alert body. The fills are left alone; only the text tones are darkened, so
 * the palette still reads as the same palette.
 *
 * Each value below is the darkest-hue-preserving tone that clears 4.5:1 on
 * white AND on its own subtle background. Found by axe on the notifications
 * and account pages.
 */
.btn-outline-danger {
  --tb-btn-color: #b02a37; /* 5.72:1 on #ffffff */
  --tb-btn-border-color: #b02a37;
  --tb-btn-hover-bg: #b02a37;
  --tb-btn-hover-border-color: #b02a37;
  --bs-btn-color: #b02a37;
  --bs-btn-border-color: #b02a37;
}

.btn-outline-success {
  --tb-btn-color: #0f5132; /* 8.42:1 */
  --tb-btn-border-color: #0f5132;
  --tb-btn-hover-bg: #0f5132;
  --tb-btn-hover-border-color: #0f5132;
  --bs-btn-color: #0f5132;
  --bs-btn-border-color: #0f5132;
}

.btn-outline-warning {
  --tb-btn-color: #8a6100; /* 4.94:1 */
  --tb-btn-border-color: #8a6100;
  --tb-btn-hover-bg: #8a6100;
  --tb-btn-hover-border-color: #8a6100;
  --tb-btn-hover-color: #ffffff;
}

.btn-outline-info {
  --tb-btn-color: #0f5c78; /* 5.93:1 */
  --tb-btn-border-color: #0f5c78;
  --tb-btn-hover-bg: #0f5c78;
  --tb-btn-hover-border-color: #0f5c78;
}

/* Alert bodies. `alert-secondary` renders in the theme's purple on a lilac
 * tint — #6356cc on #e5e1ff, 4.35:1, which fails at the 12px this app uses it
 * at. The rest are here so the family stays consistent. */
.alert-secondary {
  --tb-alert-color: #4a3fa8; /* 6.38:1 on #e5e1ff */
  --bs-alert-color: #4a3fa8;
}

.alert-danger {
  --tb-alert-color: #842029;
  --bs-alert-color: #842029;
}

.alert-success {
  --tb-alert-color: #0f5132;
  --bs-alert-color: #0f5132;
}

.alert-info {
  --tb-alert-color: #0f5c78;
  --bs-alert-color: #0f5c78;
}


/* ══════════════════════════════════════════════════════════════════════════
 * Dark theme (redesign Phase A — "Aurora Noir")
 * ══════════════════════════════════════════════════════════════════════════
 *
 * Every tone above was chosen against WHITE. On the #050405 page and the
 * #151515 card most of them fail — #565e64 is 2.9:1, #8a6100 is 3.7:1 — so
 * each gets a dark counterpart here, in the same file, so the conformance
 * rules for both themes are read together. Dark is the product default, so
 * the selector is "not light" rather than "dark": a missing attribute must
 * get these, not the white-tuned set. Ratios are against the page and the
 * card, or against the Bootstrap dark "subtle" background named.
 */
:root:not([data-theme="light"]) .fi-rating {
  color: #F2C559; /* 12.6:1 page, 11.2:1 card */
}

:root:not([data-theme="light"]) .fi-rating .fi-rating-empty {
  color: #9C9297; /* 6.8:1 page, 6.1:1 card */
}

:root:not([data-theme="light"]) .fi-featured-icon {
  color: #F2C559;
}

:root:not([data-theme="light"]) .text-success {
  color: #7EEBC6 !important; /* 6.1:1 on #025640 */
}

:root:not([data-theme="light"]) .text-danger {
  color: #FFB3C3 !important; /* 7.4:1 on #601c2c */
}

:root:not([data-theme="light"]) .text-warning {
  color: #F2C559 !important; /* 5.1:1 on #604c1c */
}

:root:not([data-theme="light"]) .text-info {
  color: #F6F2F3 !important;
}

:root:not([data-theme="light"]) .alert-warning {
  --tb-alert-color: #F2C559;
  --bs-alert-color: #F2C559;
}

:root:not([data-theme="light"]) .alert-secondary {
  --tb-alert-color: #C9C0FF; /* 7.5:1 on #322b66 */
  --bs-alert-color: #C9C0FF;
}

:root:not([data-theme="light"]) .alert-danger {
  --tb-alert-color: #FFB3C3;
  --bs-alert-color: #FFB3C3;
}

:root:not([data-theme="light"]) .alert-success {
  --tb-alert-color: #7EEBC6;
  --bs-alert-color: #7EEBC6;
}

:root:not([data-theme="light"]) .alert-info {
  --tb-alert-color: #7DD3FC; /* 6.6:1 on #0c4254 */
  --bs-alert-color: #7DD3FC;
}

:root:not([data-theme="light"]) .btn-outline-secondary {
  --tb-btn-color: #C2BBBF; /* 10.9:1 page */
  --tb-btn-border-color: #6b6b6b;
  --tb-btn-hover-bg: #C2BBBF;
  --tb-btn-hover-border-color: #C2BBBF;
  --tb-btn-hover-color: #050405;
  --bs-btn-color: #C2BBBF;
  --bs-btn-border-color: #6b6b6b;
}

:root:not([data-theme="light"]) .btn-outline-danger {
  --tb-btn-color: #FF6B86; /* 7.5:1 page, 6.7:1 card */
  --tb-btn-border-color: #FF6B86;
  --tb-btn-hover-bg: #FF6B86;
  --tb-btn-hover-border-color: #FF6B86;
  --tb-btn-hover-color: #050405;
  --bs-btn-color: #FF6B86;
  --bs-btn-border-color: #FF6B86;
}

:root:not([data-theme="light"]) .btn-outline-success {
  --tb-btn-color: #5FD39A; /* 11.0:1 page */
  --tb-btn-border-color: #5FD39A;
  --tb-btn-hover-bg: #5FD39A;
  --tb-btn-hover-border-color: #5FD39A;
  --tb-btn-hover-color: #050405;
  --bs-btn-color: #5FD39A;
  --bs-btn-border-color: #5FD39A;
}

:root:not([data-theme="light"]) .btn-outline-warning {
  --tb-btn-color: #F2C559; /* 12.6:1 page */
  --tb-btn-border-color: #F2C559;
  --tb-btn-hover-bg: #F2C559;
  --tb-btn-hover-border-color: #F2C559;
  --tb-btn-hover-color: #050405;
}

:root:not([data-theme="light"]) .btn-outline-info {
  --tb-btn-color: #7DD3FC; /* 12.3:1 page */
  --tb-btn-border-color: #7DD3FC;
  --tb-btn-hover-bg: #7DD3FC;
  --tb-btn-hover-border-color: #7DD3FC;
  --tb-btn-hover-color: #050405;
}

:root:not([data-theme="light"]) .fi-error-summary {
  border-color: #FF6B86;
}
