/* ============================================================================
   FewDesk — shared Apple-style theme.

   Every token below was MEASURED on apple.com in a live browser, not recalled:
     text            rgb(29,29,31)      = #1d1d1f
     grey surface    rgb(245,245,247)   = #f5f5f7   (27 uses, the dominant one)
     accent / button rgb(0,113,227)     = #0071e3
     button radius   980px              (34 uses — the pill)
     button padding  11px 21px, 17px, weight 400
     global nav      44px tall, rgba(255,255,255,.8),
                     backdrop-filter: saturate(1.8) blur(20px)
     type scale      12 / 14 / 17 / 21 / 24 / 28 / 34
     h1              34px, weight 600, letter-spacing -0.374px
     content grid    980px and 1024px
   Apple's Human Interface Guidelines supplied the reasoning: one accent colour,
   used only for things that are interactive; never colour alone to carry
   meaning; contrast first.

   SAFETY BY CONSTRUCTION — every selector is wrapped in :where(), which has
   ZERO specificity. Any rule a module already has beats this file, so a shared
   restyle cannot break the chat's call layout or a panel's own table. The theme
   is a floor, never a ceiling.

   It is also injected as the FIRST node in <head>, so page <style> blocks come
   later in the cascade and win ties.

   NOTE on the font: SF Pro is not licensed for the web, so it is not served.
   -apple-system picks it up on Apple devices; Windows falls back to Segoe UI,
   which is the closest native equivalent. No webfont, no layout shift.
   ========================================================================== */

:root {
  --fd-ink:      #1d1d1f;
  --fd-ink-dim:  #6e6e73;
  --fd-ink-faint:#86868b;
  --fd-surface:  #f5f5f7;
  --fd-card:     #ffffff;
  --fd-line:     rgba(0,0,0,.10);
  --fd-line-soft:rgba(0,0,0,.06);
  --fd-accent:   #0071e3;
  --fd-accent-hi:#0077ed;
  --fd-link:     #0066cc;
  --fd-ok:       #1d9a5a;
  --fd-warn:     #b25000;
  --fd-bad:      #d13b2e;

  --fd-pill:  980px;
  --fd-r-card: 18px;
  --fd-r-ctl:  12px;
  --fd-r-sm:    8px;

  --fd-grid: 980px;
  --fd-wide: 1024px;

  --fd-font: -apple-system, BlinkMacSystemFont, "SF Pro Text", "SF Pro Display",
             "Helvetica Neue", "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --fd-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;

  --fd-shadow:    0 1px 2px rgba(0,0,0,.04), 0 4px 16px rgba(0,0,0,.06);
  --fd-shadow-up: 0 2px 6px rgba(0,0,0,.06), 0 12px 32px rgba(0,0,0,.10);
  --fd-ease: cubic-bezier(.25,.1,.25,1);
}

@media (prefers-color-scheme: dark) {
  :root {
    --fd-ink:      #f5f5f7;
    --fd-ink-dim:  #a1a1a6;
    --fd-ink-faint:#8e8e93;
    --fd-surface:  #000000;
    --fd-card:     #1c1c1e;
    --fd-line:     rgba(255,255,255,.14);
    --fd-line-soft:rgba(255,255,255,.08);
    --fd-link:     #2997ff;
    --fd-shadow:    0 1px 2px rgba(0,0,0,.5), 0 4px 16px rgba(0,0,0,.4);
    --fd-shadow-up: 0 2px 6px rgba(0,0,0,.6), 0 12px 32px rgba(0,0,0,.5);
  }
}

/* ---------------------------------------------------------------- foundation */
:where(html) {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  scroll-behavior: smooth;
}
:where(body) {
  margin: 0;
  background: var(--fd-surface);
  color: var(--fd-ink);
  font-family: var(--fd-font);
  font-size: 17px;
  line-height: 1.47059;              /* apple.com's body ratio */
  letter-spacing: -.022em;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}
:where(*, *::before, *::after) { box-sizing: border-box; }

/* Type scale, straight off the measured page. */
:where(h1) { font-size: clamp(28px, 4vw, 40px); font-weight: 600;
             letter-spacing: -.015em; line-height: 1.08; margin: 0 0 .4em; }
:where(h2) { font-size: clamp(22px, 3vw, 28px); font-weight: 600;
             letter-spacing: -.014em; line-height: 1.14; margin: 1.6em 0 .5em; }
:where(h3) { font-size: 21px; font-weight: 600; letter-spacing: -.012em;
             line-height: 1.19; margin: 1.4em 0 .4em; }
:where(h4, h5, h6) { font-size: 17px; font-weight: 600; letter-spacing: -.011em;
             margin: 1.2em 0 .3em; }
:where(p) { margin: 0 0 1em; }
:where(small, .fd-small) { font-size: 14px; color: var(--fd-ink-dim); }
:where(code, pre, kbd, samp) { font-family: var(--fd-mono); font-size: .9em; }
:where(pre) { background: var(--fd-card); border: 1px solid var(--fd-line-soft);
              border-radius: var(--fd-r-ctl); padding: 14px 16px; overflow: auto; }
:where(hr) { border: 0; border-top: 1px solid var(--fd-line-soft); margin: 2em 0; }

/* One accent colour, and only for things that are interactive - HIG. */
:where(a) { color: var(--fd-link); text-decoration: none; }
:where(a:hover) { text-decoration: underline; }

/* Never remove the focus ring; HIG says do not lean on colour alone. */
:where(:focus-visible) {
  outline: 3px solid color-mix(in srgb, var(--fd-accent) 55%, transparent);
  outline-offset: 2px;
  border-radius: 6px;
}

/* --------------------------------------------------------------- the pill  */
:where(button, .btn, [role="button"], input[type="submit"], input[type="button"]) {
  font-family: inherit;
  font-size: 17px;
  font-weight: 400;
  line-height: 1.176;
  letter-spacing: -.022em;
  padding: 11px 21px;                /* measured */
  border: 0;
  border-radius: var(--fd-pill);     /* 980px */
  background: var(--fd-accent);
  color: #fff;
  cursor: pointer;
  transition: background .2s var(--fd-ease), transform .2s var(--fd-ease);
}
:where(button:hover, .btn:hover, input[type="submit"]:hover) {
  background: var(--fd-accent-hi);
}
:where(button:active, .btn:active) { transform: scale(.97); }
:where(button:disabled, .btn:disabled) { opacity: .42; cursor: not-allowed; }
:where(.btn-quiet, button.quiet) {
  background: transparent; color: var(--fd-link);
  border: 1px solid var(--fd-line); 
}

/* ------------------------------------------------------------------ controls */
:where(input, select, textarea) {
  font-family: inherit;
  font-size: 17px;
  color: var(--fd-ink);
  background: var(--fd-card);
  border: 1px solid var(--fd-line);
  border-radius: var(--fd-r-ctl);
  padding: 11px 14px;
  transition: border-color .18s var(--fd-ease), box-shadow .18s var(--fd-ease);
}
:where(input:focus, select:focus, textarea:focus) {
  outline: 0;
  border-color: var(--fd-accent);
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--fd-accent) 18%, transparent);
}
:where(input::placeholder, textarea::placeholder) { color: var(--fd-ink-faint); }
:where(label) { font-size: 14px; color: var(--fd-ink-dim); }

/* --------------------------------------------------------------------- cards */
:where(.card, .tile, .panel, .box, section.card) {
  background: var(--fd-card);
  border: 1px solid var(--fd-line-soft);
  border-radius: var(--fd-r-card);
  padding: 22px;
  box-shadow: var(--fd-shadow);
  transition: transform .28s var(--fd-ease), box-shadow .28s var(--fd-ease);
}
:where(.tile:hover, .card:hover) {
  transform: translateY(-2px);
  box-shadow: var(--fd-shadow-up);
}

/* -------------------------------------------------------------------- tables */
:where(table) {
  width: 100%;
  border-collapse: collapse;
  font-size: 14px;
  font-variant-numeric: tabular-nums;   /* figures line up */
}
:where(th) {
  text-align: left;
  font-weight: 600;
  font-size: 12px;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--fd-ink-dim);
  padding: 10px 12px;
  border-bottom: 1px solid var(--fd-line);
  white-space: nowrap;
}
:where(td) {
  padding: 11px 12px;
  border-bottom: 1px solid var(--fd-line-soft);
}
:where(tbody tr:hover) { background: color-mix(in srgb, var(--fd-accent) 4%, transparent); }

/* ------------------------------------------------------------------- layout */
:where(main, .wrap, .container, .content) {
  max-width: var(--fd-grid);
  margin-inline: auto;
  padding-inline: 22px;
}
:where(.wide) { max-width: var(--fd-wide); }

/* Honour the accessibility setting - HIG is explicit about this. */
@media (prefers-reduced-motion: reduce) {
  :where(html) { scroll-behavior: auto; }
  :where(*) { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}

/* Comfortable tap targets on a phone - 44px is Apple's documented minimum. */
@media (max-width: 640px) {
  :where(body) { font-size: 16px; }
  :where(button, .btn, input[type="submit"]) { padding: 12px 20px; min-height: 44px; }
  :where(input, select, textarea) { font-size: 16px; min-height: 44px; }
  :where(main, .wrap, .container, .content) { padding-inline: 16px; }
  :where(table) { font-size: 13px; }
  :where(th, td) { padding: 9px 8px; }
}

/* Printing a panel should not waste ink on chrome. */
@media print {
  #fdnav { display: none !important; }
  :where(body) { background: #fff; color: #000; }
}

/* __IOSZOOM__ ---------------------------------------------------------------
   Measured on 2026-08-13: #inp 15px, #q 14.5px, #grp 13.5px, #asin 15px.

   iOS Safari zooms into any focused form control whose font-size is below 16px,
   and it does not zoom back out afterwards. The visible result is a page that
   suddenly sits off-centre with the keyboard over it -- which is what "the forms
   do not sit right on mobile" looks like from the outside.

   This is the one rule in this file that is NOT inside :where(). Everything else
   here has zero specificity so a module can always overrule the theme; the theme
   is a floor, not a ceiling. But in this case the module's own 14.5px is itself
   the defect, so the correction has to outrank it. Confined to touch-capable
   narrow screens, so desktop typography is untouched.

   Source: the 16px threshold is Safari's documented behaviour on iOS; verified
   independently by measuring the computed font-size of each control above. */

/* Full-height panels get their height from nav.js via --fd-nav-h. Declared here
   with a fallback so a page still lays out correctly for the instant before
   nav.js has measured, and if nav.js fails to load at all. */
:where(:root) { --fd-nav-h: 44px; }

/* Long-press text selection and double-tap zoom on the nav's own controls are
   pure nuisance on a phone; the bar is navigation, not content. */
:where(.fdnav a, .fdnav button) { touch-action: manipulation; }

/* __PHONEROW__ ---------------------------------------------------------------
   Measured on an iPhone 14 viewport (390x844): #admin, #chpw, #lo and #diag sat
   past the right edge of the window. They are the settings row of the chat header
   and on a 390px screen there is no width for them beside the channel name.

   Off-screen is worse than cramped: a cramped control can still be tapped. So the
   row wraps and its items shrink instead of overflowing. Buttons keep a 44px
   minimum touch target, which is Apple's own guidance for the smallest thing a
   finger should have to hit.

   Applied by attribute and id rather than by a layout class, because these are the
   specific controls that were measured to overflow -- not a guess at a pattern. */
@media (max-width: 820px) {
  :where(#top, .top, header.chat-top, .chat-head) {
    flex-wrap: wrap;
    row-gap: 6px;
    padding-inline: 10px;
  }
  #admin, #chpw, #lo, #diag {
    min-height: 34px;
    padding-inline: 10px;
    font-size: 13px;
    flex: 0 0 auto;
  }
  /* the settings cluster drops to its own line rather than pushing sideways */
  :where(#top, .top, .chat-head) > :where(#admin, #chpw, #lo, #diag) {
    margin-left: 0;
  }
}
@media (max-width: 480px) {
  /* on the narrowest phones even that is too much: keep the two a person needs
     during a conversation, and move the rest behind the existing menu */
  #diag, #chpw { display: none; }
}

/* __IOSZOOM2__ --------------------------------------------------------------
   Replaces an earlier rule of mine that was scoped to `max-width: 820px`. That
   was wrong on measurement: an iPhone 14 in landscape reports 844px and an iPad
   mini reports 768px in portrait, so the very devices that zoom were falling
   outside the breakpoint half the time. Width does not identify the behaviour.

   iOS Safari zooms into any focused control under 16px and does not zoom back
   out. 16px is also simply the right size for something a person types into, so
   the rule applies everywhere and the media query is gone.

   Not inside :where() -- every other rule here has zero specificity so a module
   can overrule the theme, but a module setting 13px on an input IS the defect
   being corrected, so this one has to win. It is the only such rule. */
input, textarea, select,
input[type=text], input[type=search], input[type=email], input[type=number],
input[type=password], input[type=tel], input[type=url], input[type=date] {
  font-size: 16px !important;
}
/* a 16px input must not become wider than its container as a result */
:where(input, textarea, select) { max-width: 100%; box-sizing: border-box; }

/* __HTMLFIT__ the simpler half of the nav correction: correct the root once and
   anything sized height:100% inherits it, with no per-element stamping at all.
   Stamping remains for panels that hardcode 100dvh, because those ignore their
   parent's height by definition. */
html { height: calc(100dvh - var(--fd-nav-h, 44px)); box-sizing: border-box; }
body { min-height: 100%; }

/* __TABSCROLL__ -------------------------------------------------------------
   Measured on 2026-08-13: the Amazon Keywords tab strip put four tabs 159, 354,
   575 and 718px past the right edge of a 1440px window, and eight to ten past the
   edge of a phone. Those tabs are the only way to change what the page shows, so
   an unreachable tab is an unreachable feature -- not a cosmetic issue.

   Nine tabs cannot fit 390px in one row and should not try. The strip scrolls
   sideways instead, with the two things that make a scrollable strip discoverable:
   momentum on touch, and a fade at the edge so it is visible that more exists.
   Scroll snapping keeps a tab from being left half-cut.

   Targeted at containers that actually hold the tabs, and written so that a strip
   which already fits is completely unaffected. */
:where(.tabs, #tabs, .tabbar, [role="tablist"]) {
  display: flex;
  flex-wrap: nowrap;
  overflow-x: auto;
  overflow-y: hidden;
  -webkit-overflow-scrolling: touch;
  scroll-snap-type: x proximity;
  scrollbar-width: thin;
  gap: 6px;
  padding-inline: 4px;
  /* the fade only paints when there is something to scroll to */
  -webkit-mask-image: linear-gradient(to right, #000 0, #000 calc(100% - 22px), transparent 100%);
          mask-image: linear-gradient(to right, #000 0, #000 calc(100% - 22px), transparent 100%);
}
:where(.tabs, #tabs, .tabbar, [role="tablist"]) > * {
  flex: 0 0 auto;
  scroll-snap-align: start;
}
/* a strip that fits needs no fade and no snapping */
@supports (animation-timeline: scroll()) {
  :where(.tabs, #tabs, .tabbar, [role="tablist"]):not(:hover) { scrollbar-width: none; }
}
:where(.tabs, #tabs, .tabbar, [role="tablist"])::-webkit-scrollbar { height: 4px; }
:where(.tabs, #tabs, .tabbar, [role="tablist"])::-webkit-scrollbar-thumb {
  background: rgba(0,0,0,.22); border-radius: 4px;
}

/* __DRAWERCLOSE__ -----------------------------------------------------------
   The channel drawer covers the button that opens it, so on a phone that button
   cannot close it again. Tapping the dimmed area does work, so this was never a
   trap -- but a control that only works one way reads as broken.

   A close button is added to the drawer itself by nav.js. This sizes it to a 44px
   touch target, which is Apple's minimum for something a finger must hit, and
   keeps it clear of the notch. */
#fdDrawerClose {
  position: absolute; top: 6px; right: 6px;
  width: 40px; height: 40px; min-width: 40px;
  display: none; align-items: center; justify-content: center;
  border: 0; border-radius: 980px; cursor: pointer;
  background: rgba(120,120,128,.14); color: #1d1d1f;
  font-size: 19px; line-height: 1; z-index: 5;
  padding-top: env(safe-area-inset-top, 0px);
}
#fdDrawerClose:hover { background: rgba(120,120,128,.24); }
@media (max-width: 820px) { #fdDrawerClose { display: flex; } }
@media (prefers-color-scheme: dark) {
  #fdDrawerClose { background: rgba(120,120,128,.28); color: #f5f5f7; }
}

/* __TABSTAMP__ the stamp that stampTabs() applies. Only strips that were measured
   to overflow get it, so a strip that fits is untouched and gains no scrollbar. */
[data-fd-tabs] {
  display: flex !important;
  flex-wrap: nowrap !important;
  overflow-x: auto !important;
  overflow-y: hidden;
  -webkit-overflow-scrolling: touch;
  scroll-snap-type: x proximity;
  gap: 6px;
  -webkit-mask-image: linear-gradient(to right, #000 0, #000 calc(100% - 24px), transparent 100%);
          mask-image: linear-gradient(to right, #000 0, #000 calc(100% - 24px), transparent 100%);
}
[data-fd-tabs] > * { flex: 0 0 auto !important; scroll-snap-align: start; }
[data-fd-tabs]::-webkit-scrollbar { height: 4px; }
[data-fd-tabs]::-webkit-scrollbar-thumb { background: rgba(0,0,0,.22); border-radius: 4px; }
@media (prefers-color-scheme: dark) {
  [data-fd-tabs]::-webkit-scrollbar-thumb { background: rgba(255,255,255,.26); }
}

/* and nothing in the drawer may overlap the corner it occupies */
:where(#side, .side) > :where(ul, nav, .list, header):first-child {
  padding-right: 52px;
}

/* __DRAWERTOP__ -------------------------------------------------------------
   Measured with elementsFromPoint: the element at the drawer close button's own
   centre was a link inside NAV#fdnav (z-index 9000, sticky). The drawer is
   z-index 41. The navigation bar covers the drawer's top 44px on a phone.

   I first tried to out-rank it with z-index: 2147483000. That could never work --
   the bar is a separate stacking context at the root, and z-index only orders
   siblings within a context. Raising the number was treating the symptom.

   The real problem is bigger than my button: anything the drawer places in its
   top strip is unreachable on a phone. So the drawer starts below the bar, using
   the same measured height the rest of the layout already uses. */
@media (max-width: 820px) {
  :where(#side, .side) {
    top: var(--fd-nav-h, 44px) !important;
    height: calc(100dvh - var(--fd-nav-h, 44px)) !important;
    max-height: calc(100dvh - var(--fd-nav-h, 44px)) !important;
  }
}
#fdDrawerClose {
  /* inside the drawer, which now starts below the bar, so plain coordinates work
     and no z-index arms race is needed */
  z-index: 60;
  top: 8px;
  right: 8px;
}
/* the dimmed backdrop has to clear the bar too, or tapping near the top of it
   hits the bar instead of dismissing the drawer */
@media (max-width: 820px) {
  :where(#scrim, .scrim, .backdrop) { top: var(--fd-nav-h, 44px) !important; }
}


/* __DRAWERPAD__ --------------------------------------------------------------
   Previous attempt set `transform: translateY(44px)` on the open drawer. That
   replaced the transform the drawer uses to slide itself in, so I was overwriting
   the mechanism rather than adjusting it -- and the measured top stayed wrong.

   Padding does not participate in positioning at all, so it cannot conflict with
   however the drawer chooses to place itself. The bar covers the top 44px; the
   drawer simply stops putting anything there. */
@media (max-width: 820px) {
  :where(#side, .side) {
    padding-top: calc(var(--fd-nav-h, 44px) + 8px) !important;
    box-sizing: border-box;
  }
  #fdDrawerClose { top: calc(var(--fd-nav-h, 44px) + 8px) !important; }
}

/* __DRAWERFIXED__ ------------------------------------------------------------
   The drawer's own element begins at -71px on a phone, so a `top` set inside it
   is measured from -71 and lands above the window however small the number. Three
   attempts went into arguing with that: raising z-index, setting top, replacing
   the transform. All of them were downstream of the same fact.

   position:fixed takes the button out of the drawer's coordinate space entirely,
   so it sits where the window says rather than where the drawer says. It is shown
   only while the drawer is open. */
@media (max-width: 820px) {
  #fdDrawerClose {
    position: fixed !important;
    top: calc(var(--fd-nav-h, 44px) + 8px) !important;
    left: auto !important;
    right: auto !important;
    /* just inside the drawer's right edge; the drawer is min(78%, 300px) */
    inset-inline-start: calc(min(78vw, 300px) - 50px) !important;
    z-index: 9500 !important;   /* above the drawer (41), below the bar (9000)+ */
  }
  /* only while it is open, so it cannot float over a closed drawer */
  #fdDrawerClose { display: none !important; }
  :where(#side, .side).open ~ #fdDrawerClose,
  :where(#side, .side).open #fdDrawerClose { display: flex !important; }
}

/* and one level deeper, where the scrolling list actually lives */
[data-fd-vh] > main > *, [data-fd-vh] > .main > * { min-height: 0; }
/* the composer must never be the thing that gets pushed out */
[data-fd-vh] > .comp, [data-fd-vh] > main > .comp,
[data-fd-vh] .comp { flex: 0 0 auto; }
