/*
 * Freedom Nation design-system extensions (E01-S12, R-DS-EXT-1 to 3).
 * Every class here is fnx- and documented in web/design-system/EXTENSIONS.md.
 * Composed only from the design system's tokens and primitives: no new
 * colour, font, radius, shadow or spacing value. Breakpoints are the
 * container widths 600/760/900 only; prefers-reduced-motion turns motion off.
 */

/* ── SkipLink: a .fn-btn shown only while it has focus. It appears at once
   (no transform transition), so it is on screen the moment it is focused. ── */
.fnx-skip { position: absolute; top: var(--space-2); left: var(--space-4); z-index: 6; transform: translateY(-200%); transition: none; }
.fnx-skip:focus, .fnx-skip:focus-visible { transform: none; }

/* ── HitArea (IC20-12): controls the design system draws below 44 × 44
   (icon buttons 40px, the save heart 36px, .fn-seg buttons about 32px,
   --sm buttons 36px) keep their size; an invisible ::before centred on the
   control makes the hit area at least 44 × 44 (calc(var(--space-12) -
   var(--space-1))). It paints nothing. A control the design system already
   positions (the save heart is absolute) keeps its own position. ── */
.fnx-hit { position: relative; }
.fnx-hit::before {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: max(100%, calc(var(--space-12) - var(--space-1)));
  height: max(100%, calc(var(--space-12) - var(--space-1)));
  transform: translate(-50%, -50%);
}

/* ── FocusRing (IC20-16): the standard's ring is 2px solid focus with a 2px
   offset (R-DS-A11Y-3), as bundle.css draws it for every control except
   .fn-input:focus, which uses a 1px offset. Only the offset changes, and
   only while the ring shows. ── */
:where(.fn, .fn-screen) .fn-input:focus-visible { outline-offset: calc(var(--space-1) / 2); }

/* ── Dialog/Sheet and NavSheet: native <dialog> on surface ── */
.fnx-dialog, .fnx-sheet {
  box-sizing: border-box;
  width: calc(100% - var(--space-8));
  max-width: 480px;
  max-height: calc(100% - var(--space-8));
  overflow: auto;
  padding: var(--space-6);
  background: var(--surface);
  color: var(--ink);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lift);
}
.fnx-dialog::backdrop, .fnx-sheet::backdrop { background: var(--surface-sunk); opacity: .8; }
.fnx-dialog__actions { justify-content: flex-end; }
/* A dialog's figure: page 1 of a document in the Chargeback Defense
   preview (E13-S08 AC7), fitted to the dialog on the page's paper. */
.fnx-dialog__figure { display: block; width: 100%; height: auto; border: 1px solid var(--line); border-radius: var(--radius-md); background: var(--surface); }

/* NavSheet: always a bottom sheet. */
.fnx-sheet { margin: auto 0 0; width: 100%; max-width: none; max-height: 85%; border-bottom: 0; border-radius: var(--radius-lg) var(--radius-lg) 0 0; padding: var(--space-4) var(--space-4) var(--space-8); }

/* Dialog: a bottom sheet below 600px. */
@container screen (max-width: 599.98px) {
  .fnx-dialog { margin: auto 0 0; width: 100%; max-width: none; border-bottom: 0; border-radius: var(--radius-lg) var(--radius-lg) 0 0; padding: var(--space-4) var(--space-4) var(--space-8); }
  .fnx-dialog__actions .fn-btn { flex: 1; }
}

/* ── Toast/Notice: an icon plus words on a soft tint, in its strong colour ── */
.fnx-notice { display: flex; align-items: center; gap: var(--space-3); padding: var(--space-3) var(--space-4); border-radius: var(--radius-md); }
.fnx-notice > p { flex: 1; min-width: 0; margin: 0; }
.fnx-notice--info { background: var(--sky-soft); color: var(--sky); }
.fnx-notice--success { background: var(--pine-soft); color: var(--pine); }
.fnx-notice--warning { background: var(--clay-soft); color: var(--clay); }
.fnx-notice--danger { background: var(--danger-soft); color: var(--danger); }
.fnx-notice .fn-btn--ghost { color: inherit; }

/* The polite live region, sticky at the bottom of the screen, above the
   tab bar and the sticky CTA on phones. */
.fnx-toasts { position: sticky; bottom: var(--space-4); z-index: 5; display: flex; flex-direction: column; align-items: center; gap: var(--space-2); padding: 0 var(--space-4); pointer-events: none; }
.fnx-toast { pointer-events: auto; width: 100%; max-width: 480px; box-shadow: var(--shadow-lift); }
.fn-app ~ .fnx-toasts, .fn-sticky-cta ~ .fnx-toasts { bottom: calc(var(--space-16) + var(--space-6)); }
.fn-app--admin ~ .fnx-toasts { bottom: var(--space-4); }
@container screen (min-width: 760px) { .fn-sticky-cta ~ .fnx-toasts { bottom: var(--space-4); } }
@container screen (min-width: 900px) { .fn-app ~ .fnx-toasts { bottom: var(--space-4); } }

/* ── Tabs: the WAI-ARIA tab list on .fn-seg; the selected tab looks like
   the pressed segment ── */
.fnx-tabs [role="tab"][aria-selected="true"] { background: var(--surface); color: var(--ink); box-shadow: var(--shadow-soft); }
/* A long tab list (the admin citizen record, E13-S06 AC7) wraps instead
   of scrolling sideways; wrapped rows sit on a card-like radius. */
.fnx-tabs--wrap { flex-wrap: wrap; max-width: 100%; border-radius: var(--radius-lg); }
/* The panel takes focus (tabindex="0"), so it is a 44 px target at least
   even when its content is one line (found by the gallery's target gate). */
.fnx-tabpanel { display: flex; flex-direction: column; gap: var(--space-4); min-height: calc(var(--space-12) - var(--space-1)); }

/* ── Pagination ── */
.fnx-pagination { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); }

/* ── States: empty, loading, error, success ── */
.fnx-state { align-items: center; text-align: center; }
.fnx-state--loading { display: flex; flex-direction: column; align-items: stretch; gap: var(--space-3); }
.fnx-skeleton { display: block; height: var(--space-4); border-radius: var(--radius-sm); background: var(--surface-sunk); animation: fnx-pulse 1.4s ease-in-out infinite; }
.fnx-skeleton:nth-child(2) { width: 80%; }
.fnx-skeleton:nth-child(3) { width: 60%; }
@keyframes fnx-pulse { 50% { opacity: .55; } }

/* ── Monogram: "FN" in Fraunces 650 (via .t-heading), on-pine on pine ── */
.fnx-monogram { display: inline-grid; place-items: center; width: 48px; height: 48px; border-radius: var(--radius-md); background: var(--pine); color: var(--on-pine); font-weight: 650; letter-spacing: 0; }

/* ── DataFill: a data-driven fill colour passed as --fnx-fill (IC20-13).
   The reference markup sets these inline as background:var(--token); the
   partials pass the token as a custom property instead, so inline styles
   carry only geometry and custom properties. The selectors outrank the
   design system's own fills (.fn-progress > span, .fn-legend i) only where
   the partial asked for a token. ── */
.fn-progress > span.fnx-fill, .fn-legend i.fnx-fill { background: var(--fnx-fill); }

/* ── Milestone (E01-S10, MemberLearn): a large avatar disc in wheat for an
   earned milestone (style="background:var(--wheat);color:var(--on-wheat)"),
   sunk for the next one (style="background:var(--surface-sunk);
   color:var(--ink-muted)"). The words beside it say which. ── */
.fnx-milestone { background: var(--wheat); color: var(--on-wheat); }
.fnx-milestone--next { background: var(--surface-sunk); color: var(--ink-muted); }

/* ── FeatureCard (E01-S10, MemberLearn): the continue-lesson card on the
   clay soft tint (style="background:var(--clay-soft);border-color:
   transparent;box-shadow:none"); its badge, bar and art sit on surface
   (style="background:var(--surface)"), the art with radius-lg; its two
   columns are centred (style="align-items:center"). ── */
.fnx-feature { background: var(--clay-soft); border-color: transparent; box-shadow: none; }
.fnx-feature .fn-badge, .fnx-feature .fn-progress, .fnx-feature .fn-art { background: var(--surface); }
.fnx-feature .fn-art { border-radius: var(--radius-lg); }
.fnx-feature > .fn-split { align-items: center; }

/* ── Specimen (E01-S11): the component gallery's frames. Each is a
   .fn-screen of a fixed width (375, 768 or 1280 px: the widths the rendered
   gates use), so the components respond to it as to a page, inside a
   region that scrolls sideways when the page is narrower, so the page
   itself never does. Frames take their content's height. A dialog or sheet
   rendered open sits in the frame's flow. Below 760px the gallery page
   shows the 375 px frames only: the wider ones are for wider screens. ── */
.fnx-frame { max-width: 100%; min-height: var(--space-12); overflow-x: auto; border: 1px solid var(--line); border-radius: var(--radius-md); }
.fnx-frame__screen { position: relative; height: auto; }
.fnx-frame--375 > .fnx-frame__screen { width: 375px; }
.fnx-frame--768 > .fnx-frame__screen { width: 768px; }
.fnx-frame--1280 > .fnx-frame__screen { width: 1280px; }
@container screen (max-width: 759.98px) {
  .fnx-frame--768, .fnx-frame--1280 { display: none; }
}
/* From 760px a frame wider than the page's content column runs past it
   and the page scrolls sideways, rather than the frame scrolling inside
   itself: a control in a 1280 px frame is then never clipped by its frame. */
@container screen (min-width: 760px) {
  .fnx-frame { max-width: none; overflow: visible; }
  .fnx-frame--768, .fnx-frame--1280 { width: max-content; }
}
/* A card or an open sheet is drawn at the width it has in a page: a grid
   column, or the dialog's width. */
.fnx-specimen > .fn-parcel { max-width: 400px; }
.fnx-specimen dialog[open] { max-width: 480px; }
.fnx-specimen { padding: var(--space-4); }
/* An entry: its heading, the partial call (long calls wrap rather than
   widen the page), the rule, then its frames. */
.fnx-entry { padding-block: var(--space-4); border-top: 1px solid var(--line); }
.fnx-call { overflow-wrap: anywhere; }
.fnx-specimen dialog[open] { position: static; margin: 0; }

/* ── RecordTable (E13): the record column of a DataTable (a name and one
   muted line, long values wrap), the actions column, and the phone list,
   whose rows wrap so a full-size action never widens the page. ── */
.fnx-record { min-width: 0; overflow-wrap: anywhere; }
.fnx-record a { color: inherit; }
.fnx-actions { flex-wrap: wrap; gap: var(--space-2); }
.fnx-actions form { display: contents; }
.fnx-record-list > div { flex-wrap: wrap; }
.fnx-record-list > div > .fnx-actions { flex: 1 1 100%; }
/* A DataTable row with several actions (E06 Documents): on phones the
   actions take their own line after the badge, as in RecordTable, and a
   long label wraps inside its button instead of leaving the card. */
.fn-list > div:has(> .fnx-actions) { flex-wrap: wrap; }
.fn-list > div > .fnx-actions { flex: 1 1 100%; }
.fn-list > div > .fnx-actions .fn-btn { white-space: normal; text-align: center; }

/* ── DiffView (E13-S03): each changed field, its value before on
   surface-sunk and after on pine-soft, each led by its word. ── */
.fnx-diff { display: flex; flex-direction: column; gap: var(--space-3); margin: 0; }
/* The field on its own line, then before and after side by side: the
   view also sits in narrow asides, so it does not depend on the screen. */
.fnx-diff__row { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: var(--space-2); align-items: start; }
.fnx-diff dt { grid-column: 1 / -1; font-weight: 650; }
.fnx-diff dd { margin: 0; padding: var(--space-2) var(--space-3); border-radius: var(--radius-sm); overflow-wrap: anywhere; }
.fnx-diff dd .fn-eyebrow { display: block; }
.fnx-diff__before { background: var(--surface-sunk); color: var(--ink); }
.fnx-diff__after, .fnx-diff__after .fn-eyebrow { background: var(--pine-soft); color: var(--pine); }

/* ── Disclosure (E02-S01): a question and its answer in a native <details>
   card. The summary is a 44px row with the chevron, which turns when the
   card is open; the browser's own marker is hidden. ── */
.fnx-disclosure { padding-block: var(--space-2); }
.fnx-disclosure > summary { list-style: none; display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); min-height: 44px; cursor: pointer; }
.fnx-disclosure > summary::-webkit-details-marker { display: none; }
.fnx-disclosure > summary > svg { flex: none; transition: transform .2s; }
.fnx-disclosure[open] > summary > svg { transform: rotate(180deg); }
.fnx-disclosure > p { padding-bottom: var(--space-2); }

/* ── Prose (E02-S01, E02-S07, E02-S08): Markdown from the content editor
   and the owner-adopted legal texts, after the sanitiser, which adds the
   type classes (.fn-h2, .fn-h3) and nothing else. Spacing between blocks,
   list indents, quotes as a line-ruled aside, links in the brand colour,
   images and the allow-listed video embed at the column's width. A table
   is a .fn-table from 760px and a .fn-list below it (R-DS-LAY-4). ── */
.fnx-prose { display: grid; gap: var(--space-4); max-width: 760px; }
.fnx-prose > h2, .fnx-prose > h3, .fnx-prose > h4 { margin-top: var(--space-4); }
.fnx-prose ul, .fnx-prose ol { padding-left: var(--space-6); display: grid; gap: var(--space-2); }
.fnx-prose li > ul, .fnx-prose li > ol { margin-top: var(--space-2); }
.fnx-prose a { color: var(--pine); text-decoration: underline; }
/* An email address stays on one line: a break at its hyphen would split the
   link's box across two lines, so its focus ring would sit over other words
   (D114 fills the legal texts with memberservices@gc-usa.com). */
.fnx-prose a[href^="mailto:"] { white-space: nowrap; }
.fnx-prose blockquote { border-left: 2px solid var(--line); padding-left: var(--space-4); color: var(--ink-muted); }
.fnx-prose img { max-width: 100%; height: auto; border-radius: var(--radius-lg); }
.fnx-embed { width: 100%; aspect-ratio: 16 / 9; border: 0; border-radius: var(--radius-lg); }
.fnx-prose-table { padding: 0; overflow: hidden; }
.fnx-prose-table > .fn-list { padding: var(--space-2) var(--space-4); }

/* ── NewsletterSignup (E02-S11): the website footer's sign-up, one email
   field and a pine Subscribe button side by side, wrapping on phones; the
   button sits on the field's baseline. ── */
.fn-footer .fnx-newsletter { align-items: end; flex: 1 1 320px; }
.fnx-newsletter > .fn-field { flex: 1 1 220px; }

/* ── OGCard (E02-S12): the 1200 x 630 Open Graph card captured by headless
   Chromium: the wordmark and the title on ground beside the page's contour
   art. Its admin preview shows it at full size in a region that scrolls
   sideways on narrow screens, so the page itself never does. ── */
.fnx-og { width: 1200px; height: 630px; display: grid; grid-template-columns: 1.3fr 1fr; gap: var(--space-12); align-items: stretch; padding: var(--space-16); background: var(--ground); color: var(--ink); }
.fnx-og__text { display: flex; flex-direction: column; justify-content: space-between; }
.fnx-og__art { aspect-ratio: auto; border-radius: var(--radius-lg); }
.fnx-og-preview { max-width: 100%; overflow-x: auto; border: 1px solid var(--line); border-radius: var(--radius-md); }

@media (prefers-reduced-motion: reduce) {
  .fnx-skeleton { animation: none; }
}

/* ── E03 extensions (registration, sign-in, security; EXTENSIONS.md) ── */

/* AuthFrame: the composed auth card pages. The wordmark, then one centred
   column holding the page's .fn-card, on ground. */
.fnx-auth { display: flex; flex-direction: column; align-items: center; gap: var(--space-6); min-height: 100%; padding: var(--space-8) var(--space-4) var(--space-16); }
.fnx-auth > * { width: 100%; max-width: 560px; }
.fnx-auth__brand { display: flex; justify-content: center; }

/* ChoiceList: native checkboxes in a fieldset; each label row is a 44px
   target. The legend reads like a field label (.fn-small, weight 600). */
.fnx-choices { border: 0; margin: 0; padding: 0; min-width: 0; display: flex; flex-direction: column; gap: var(--space-1); }
.fnx-choices > legend { padding: 0; margin-bottom: var(--space-1); font-weight: 600; }
.fnx-choice { display: flex; align-items: center; gap: var(--space-3); min-height: 44px; cursor: pointer; }
.fnx-choice > input { flex: none; width: 24px; height: 24px; margin: 0; color: inherit; accent-color: var(--pine); }
.fnx-choices__error, .fnx-photo__error { color: var(--danger); }

/* PasswordField: the show/hide toggle sits under the field. */
.fnx-password { display: flex; flex-direction: column; align-items: flex-start; gap: var(--space-1); }
.fnx-password > .fn-field { align-self: stretch; }

/* PhotoUpload: the large avatar preview beside the two file inputs. */
.fnx-photo { border: 0; margin: 0; padding: 0; min-width: 0; display: flex; flex-direction: column; gap: var(--space-2); }
.fnx-photo > legend { padding: 0; margin-bottom: var(--space-1); font-weight: 600; }
.fnx-photo__row { display: flex; align-items: flex-start; gap: var(--space-4); }
.fnx-photo__inputs { flex: 1; min-width: 0; }
.fnx-avatar-photo { object-fit: cover; }

/* CitizenId: the eyebrow, the ID in Figtree 650 tabular figures, the copy
   button. In the sidebar it is a flat card at the foot. */
.fnx-cid { display: flex; flex-direction: column; gap: var(--space-1); }
.fnx-cid .fn-row { gap: var(--space-2); }
.fnx-cid--side { margin-top: auto; padding: var(--space-4); }

/* QrDisplay: the code in ink on surface, the key below it. */
.fnx-qr { margin: 0; display: flex; flex-direction: column; align-items: flex-start; gap: var(--space-3); }
.fnx-qr__code { padding: var(--space-3); background: var(--surface); color: var(--ink); border: 1px solid var(--line); border-radius: var(--radius-md); }
.fnx-qr__svg { display: block; width: 192px; height: 192px; }
.fnx-qr__key { overflow-wrap: anywhere; }

/* ── E08 extensions (land registry; EXTENSIONS.md "LotMap", "FileUpload") ── */

/* LotMap: the lots as SVG shapes on a sunk well (or the muted basemap).
   Fill and stroke are exactly the R-DS-EXT-4 tokens; the hatched statuses
   add a pattern drawn in their stroke token over the fill, so status is
   never colour alone. Strokes do not scale with the view box. */
.fnx-map { display: flex; flex-direction: column; gap: var(--space-3); }
.fnx-map__frame { position: relative; overflow: hidden; border-radius: var(--radius-lg); border: 1px solid var(--line); background: var(--surface-sunk); }
.fnx-map__svg { display: block; width: 100%; height: auto; aspect-ratio: 4 / 3; touch-action: none; }
.fnx-map__tiles image { opacity: .45; filter: grayscale(1); }
.fnx-map__water { fill: var(--sky); stroke: var(--sky); }
.fnx-lot { stroke-width: 2; vector-effect: non-scaling-stroke; stroke-linejoin: round; }
.fnx-lot-hatch { stroke: none; pointer-events: none; }
.fnx-lot--available { fill: var(--surface); stroke: var(--line-strong); }
.fnx-lot--reserved { fill: var(--clay-soft); stroke: var(--clay); }
.fnx-lot--under-lease { fill: var(--pine-soft); stroke: var(--pine); }
.fnx-lot--deeded { fill: var(--pine); stroke: var(--pine-deep); }
.fnx-lot--not-for-sale { fill: var(--surface-sunk); stroke: var(--line); }
.fnx-lot--reconciling { fill: var(--clay-soft); stroke: var(--warning); stroke-dasharray: 6 4; }
.fnx-lot--new { fill: none; stroke: var(--clay); stroke-width: 3; }
.fnx-lot--current { fill: none; stroke: var(--ink-muted); stroke-dasharray: 4 4; }
.fnx-hatch { fill: none; stroke-width: 1.5; stroke-linecap: round; }
.fnx-hatch--reserved { stroke: var(--clay); stroke-width: 2.5; }
.fnx-hatch--under-lease { stroke: var(--pine); }
.fnx-hatch--deeded { stroke: var(--pine-deep); }
.fnx-hatch--not-for-sale { stroke: var(--line-strong); }
.fnx-hatch--reconciling { stroke: var(--warning); }
.fnx-map__lot { cursor: pointer; }
.fnx-map__lot.is-selected .fnx-lot { stroke: var(--focus); stroke-width: 4; stroke-dasharray: none; }
.fnx-map__controls { justify-content: flex-end; gap: var(--space-2); }
.fnx-map__controls[hidden] { display: none; }
.fnx-map__keys { position: absolute; width: 0; height: 0; overflow: hidden; }
.fnx-swatch { display: inline-block; width: 16px; height: 16px; margin-right: var(--space-1); vertical-align: -3px; }
.fnx-swatch .fnx-lot { stroke-width: 2; }
@media (prefers-reduced-motion: reduce) { .fnx-map__svg { transition: none; } }

/* FileUpload: a ds/field file input (with the D84 location notice) and a
   progress bar that lotupload.js fills while it sends the file in chunks
   of 10 MB or less. */
.fnx-upload { display: flex; flex-direction: column; gap: var(--space-2); }
.fnx-upload__status[hidden] { display: none; }

/* ── Learning (E05). ExamQuestion: the question is the fieldset's legend;
   options reuse the ChoiceList rows (44px, 24px boxes, 16px text); an
   ordering item lists its steps with Move up and Move down (WCAG 2.5.7). ── */
.fnx-question { border: 0; margin: 0; padding: 0; min-width: 0; display: flex; flex-direction: column; gap: var(--space-3); }
.fnx-question__legend { padding: 0; margin-bottom: var(--space-2); display: flex; flex-direction: column; gap: var(--space-2); }
.fnx-question__stem { font-weight: 600; }
.fnx-question__options { display: flex; flex-direction: column; gap: var(--space-2); }
.fnx-question__option { padding: var(--space-2) var(--space-3); border: 1px solid var(--line); border-radius: var(--radius-md); background: var(--surface); }
.fnx-question__option:has(input:checked) { border-color: var(--pine); background: var(--pine-soft); }
.fnx-order { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--space-2); }
.fnx-order__item { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3); padding: var(--space-3); border: 1px solid var(--line); border-radius: var(--radius-md); background: var(--surface); }
.fnx-order__n { flex: none; min-width: 24px; font-weight: 650; color: var(--ink-muted); }
.fnx-order__label { flex: 1; min-width: 0; }
.fnx-order__moves { flex: none; gap: var(--space-2); }

/* The timer: the time left in tabular figures with its label; the
   five-minute warning is a Toast/Notice in the page. */
.fnx-timer { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2) var(--space-3); }
.fnx-timer__left { font-weight: 650; }

/* ChatThread: the log scrolls inside the card; the learner's messages sit
   on the right on pine-soft, the other party's on the left on
   surface-sunk, each with its author in words. */
.fnx-chat__log { display: flex; flex-direction: column; gap: var(--space-3); max-height: 480px; overflow-y: auto; padding: var(--space-1); }
.fnx-msg { display: flex; flex-direction: column; gap: var(--space-1); max-width: 85%; align-self: flex-start; padding: var(--space-3) var(--space-4); border-radius: var(--radius-lg); background: var(--surface-sunk); color: var(--ink); }
.fnx-msg > p { margin: 0; white-space: pre-wrap; }
.fnx-msg--mine { align-self: flex-end; background: var(--pine-soft); }
.fnx-msg--new { animation: fnx-msg-in 160ms ease-out; }
@keyframes fnx-msg-in { from { opacity: 0; } to { opacity: 1; } }

/* VideoPlayer: the video fills the card's width at 16:9; captions (::cue)
   are Figtree at body size on token colours; the control bar is the
   design system's icon button, range and outline buttons. */
.fnx-video { margin: 0; }
.fnx-video__stage { border-radius: var(--radius-lg); overflow: hidden; background: var(--surface-sunk); }
.fnx-video__stage > div, .fnx-video__media { display: block; width: 100%; height: auto; aspect-ratio: 16 / 9; }
.fnx-video__media::cue { color: var(--ink); background: var(--surface); }
.fnx-video__bar { align-items: center; gap: var(--space-2) var(--space-3); }
.fnx-video__seek { flex: 1 1 160px; min-width: 120px; min-height: 44px; }
.fnx-video__speed { display: inline-flex; align-items: center; gap: var(--space-2); }
.fnx-video__speed > .fn-input { width: auto; }

/* VideoUpload (E05's FileUpload): the progress bar and status appear under the field once an
   upload starts. */
.fnx-video-upload__progress { max-width: 560px; }

/* ── E06 extensions (documents and signing; EXTENSIONS.md) ── */

/* SignaturePad: the typed signature and its preview in Fraunces
   (.fn-quote), or the drawing area. Every button is 44px. */
.fnx-sigpad { border: 0; margin: 0; padding: 0; min-width: 0; display: flex; flex-direction: column; gap: var(--space-3); }
.fnx-sigpad > legend { padding: 0; margin-bottom: var(--space-1); font-weight: 600; }
.fnx-sigpad__typed, .fnx-sigpad__draw { display: flex; flex-direction: column; gap: var(--space-3); }
/* The hidden attribute wins over the flex display: the drawing area stays
   hidden until documents.js shows it. */
.fnx-sigpad__typed[hidden], .fnx-sigpad__draw[hidden], .fnx-doc-upload__progress[hidden] { display: none; }
.fnx-sigpad__preview { display: flex; flex-direction: column; gap: var(--space-1); min-height: 88px; }
.fnx-sigpad__preview > p { margin: 0; overflow-wrap: anywhere; }
.fnx-sigpad__canvas { display: block; width: 100%; max-width: 640px; aspect-ratio: 16 / 5; background: var(--surface); border: 1px dashed var(--line-strong); border-radius: var(--radius-md); touch-action: none; cursor: crosshair; }
.fnx-sigpad__ink { color: var(--ink); }

/* DocumentViewer: the printed count beside the bar, the page, the pager. */
.fnx-viewer { display: flex; flex-direction: column; gap: var(--space-4); }
.fnx-viewer__read { display: grid; grid-template-columns: auto minmax(0, 1fr); align-items: center; gap: var(--space-3); }
.fnx-viewer__read > p { margin: 0; }
.fnx-viewer__page { overflow-wrap: anywhere; }
.fnx-viewer__page > :first-child { margin-top: 0; }
.fnx-viewer__page > :last-child { margin-bottom: 0; }
.fnx-viewer__page table { width: 100%; border-collapse: collapse; table-layout: fixed; }
.fnx-viewer__page :is(th, td) { padding: var(--space-2); border-bottom: 1px solid var(--line); text-align: left; vertical-align: top; overflow-wrap: anywhere; }
.fnx-viewer__page hr { border: 0; border-top: 1px solid var(--line); }
.fnx-viewer__nav { display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: var(--space-3); }
.fnx-viewer__nav > :last-child { justify-self: end; }

/* DocumentUpload (E06's FileUpload): the file field, then the chunked upload's progress. */
.fnx-doc-upload { display: flex; flex-direction: column; gap: var(--space-2); }
.fnx-doc-upload__progress { display: flex; flex-direction: column; gap: var(--space-1); }
.fnx-doc-upload__fill { width: var(--fnx-doc-upload, 0%); }

/* ── Gallery (E13-S18 AC13): a record's photos, each a card holding its
   .fn-art frame, caption and (in the admin) its actions ── */
.fnx-gallery > figure { margin: 0; }

/* ── Wide DataTable (E13-S09): a table with more columns than a tablet
   holds keeps its .fn-list up to the 900px container breakpoint, so it
   never runs past its card (DataTable README: no sideways scroll) ── */
@container screen (min-width: 760px) {
  .fn-table.fnx-table-wide { display: none; }
  .fn-list.fn-show-sm.fnx-list-wide { display: flex !important; }
}
@container screen (min-width: 900px) {
  .fn-table.fnx-table-wide { display: table; }
  .fn-list.fn-show-sm.fnx-list-wide { display: none !important; }
}
/* ── Notifications (E12; EXTENSIONS.md "Notifications (E12)") ── */

/* Switch (E12-S09 AC7): a native checkbox with role="switch" over a
   pill track; the label is the 44px hit area; the 2px focus ring is drawn
   on the track while the hidden input has focus; the printed word (On or
   Off) follows the checked state, so the state is never colour alone. */
.fnx-switch { position: relative; display: inline-flex; align-items: center; gap: var(--space-2); min-height: 44px; min-width: 44px; cursor: pointer; }
.fnx-switch__input { position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; opacity: 0; cursor: pointer; color: inherit; background: transparent; }
.fnx-switch__track { position: relative; flex: none; width: calc(var(--space-8) + var(--space-2)); height: var(--space-6); border-radius: var(--radius-pill); background: var(--line-strong); }
.fnx-switch__track::after { content: ""; position: absolute; top: calc(var(--space-1) - 1px); left: calc(var(--space-1) - 1px); width: calc(var(--space-4) + var(--space-1) - 2px); height: calc(var(--space-4) + var(--space-1) - 2px); border-radius: var(--radius-pill); background: var(--surface); box-shadow: var(--shadow-soft); }
.fnx-switch__input:checked + .fnx-switch__track { background: var(--pine); }
.fnx-switch__input:checked + .fnx-switch__track::after { transform: translateX(var(--space-4)); }
.fnx-switch__input:focus-visible + .fnx-switch__track { outline: 2px solid var(--focus); outline-offset: 2px; }
.fnx-switch__input:disabled { cursor: not-allowed; }
.fnx-switch__input:disabled ~ .fnx-switch__label, .fnx-switch__input:disabled ~ .fn-small { color: var(--ink-muted); }
.fnx-switch__input:disabled + .fnx-switch__track { background: var(--surface-sunk); border: 1px dashed var(--line-strong); }
.fnx-switch__input:checked ~ .fnx-switch__off, .fnx-switch__input:not(:checked) ~ .fnx-switch__on { display: none; }
.fnx-switch__on, .fnx-switch__off { min-width: var(--space-6); color: var(--ink-muted); }
.fnx-switch__track, .fnx-switch__track::after { transition: background .15s, transform .15s; }

/* Switch matrix (E12-S09 AC6): rows stack below 760px; from 760px the
   switches line up in columns under the channel headings. */
.fnx-matrix > .fnx-matrix__head { display: none; }
.fnx-matrix > .fnx-matrix__row { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-2); align-items: start; }
.fnx-matrix__cell { min-width: 0; }
@container screen (min-width: 760px) {
  .fnx-matrix > .fnx-matrix__head, .fnx-matrix > .fnx-matrix__row { display: grid; grid-template-columns: minmax(0, 1fr) repeat(3, minmax(calc(var(--space-16) * 2), max-content)); gap: var(--space-4); align-items: center; }
  .fnx-matrix__locked { grid-column: 2 / -1; }
}

/* NotificationCentre (E12-S08 AC6): a full-height sheet below 900px, a
   panel at the top right from 900px. */
.fnx-notify { max-height: 100%; height: 100%; border-radius: 0; }
.fnx-notify__body { min-height: calc(var(--space-12) * 2); }
@container screen (min-width: 900px) {
  .fnx-notify { margin: var(--space-16) var(--space-6) auto auto; width: calc(var(--space-16) * 7); max-width: calc(100% - var(--space-12)); height: auto; max-height: calc(100% - var(--space-16) - var(--space-6)); border: 1px solid var(--line); border-radius: var(--radius-lg); padding: var(--space-6); }
}

/* The shell's notice band (E12-S11 AC6, E12-S12 AC7): above the page, in
   the page's own column. */
.fnx-shell-notice { margin-bottom: var(--space-4); }
