/* tonal type scale — the ONE place text sizes are defined (2026-09-22).
   Kyle: "i thought that was how it was built." It wasn't: every rule hard-coded
   its own px, ~20 distinct values, so mobile could only be fixed one selector
   at a time. Now every text size in the app is one of these six tokens, and a
   phone steps the whole scale up by one pixel in the block below.

   The voices (docs/UI-PATTERNS.md "Type scale") map onto the tokens:
     --fs-eyebrow  10px  Eyebrow — caps labels that NAME a cell; also the floor
     --fs-caption  11px  small caps pills / buttons, footer, fine print
     --fs-label    12px  Label — records, names, reviews, tile titles, inputs
     --fs-ui       13px  row titles, menu items, controls
     --fs-lead     14px  sheet options, larger control text
     --fs-body     15px  Body — the one reading paragraph (.detail-synopsis)

   NOT tokens, on purpose: display serif titles (>=16px — already large, and they
   carry their own breakpoints), glyph sizes (stars, hearts, emoji, ×), and the
   16px iOS no-zoom rule on focused inputs. Doc pages' 14.5/15.5 reading voice
   (--read) is its own deliberate voice and stays put.

   RULE: never write a text font-size in px again. Pick a token. If none fits,
   the scale is what changes, here, for everyone. */
:root {
  --fs-eyebrow: 10px;
  --fs-caption: 11px;
  --fs-label: 12px;
  --fs-ui: 13px;
  --fs-lead: 14px;
  --fs-body: 15px;
  /* Form text. Equals --fs-label on desktop; 16px on touch, where iOS zooms
     the page when a focused field's text is under 16px. */
  --fs-field: 12px;
}

/* Phones (and phones in landscape). Kyle 2026-09-22: "the font on mobile…
   feels slightly small overall", then off staging: "i don't like how forms
   text is so large and the body copy is so small." iOS forces every input to
   16px (anything smaller zooms the page on focus), so everything steps up +2
   (round 3: eyebrows at +1 read "too small" beside the bigger body). Caps at
   12px still carry more visual weight than 14px lowercase, so the eyebrow stays
   one step under the label it names. Order holds:
   eyebrow < caption < label < ui < input(16) < body. */
/* PHONES ONLY, not narrow windows (Kyle 2026-09-22: dragging a desktop window
   down to phone width made all the text jump up, "that might make sense for my
   phone but i dislike that… on desktop"). The step now needs a coarse pointer
   as well as the width, so a desktop browser keeps the desktop scale at any size. */
@media (pointer: coarse) and (max-width: 600px), (pointer: coarse) and (max-height: 500px) {
  :root {
    --fs-eyebrow: 12px;
    --fs-caption: 13px;
    --fs-label: 14px;
    --fs-ui: 15px;
    --fs-lead: 16px;
    --fs-body: 17px;
  }
}

/* Touch devices: iOS zooms on a focused field under 16px. Kyle wants form text
   and body copy the SAME size — raising Settings copy to 16 was tried and read
   "way too large", so the fields come DOWN instead: they keep a real 16px
   font-size (no zoom) and are drawn at 0.875 scale (= 14px, the phone label
   size). See .settings-input in profile.html. */
@media (hover: none) and (pointer: coarse) {
  :root { --fs-field: 16px; }
}

/* ── TOUCH TARGETS (Kyle 2026-09-22: "are there any other buttons forms etc
   site-wide we need to address the height of?" → "yes all three") ──────────
   44px is the floor for anything a thumb has to hit. Desktop is untouched: all
   of this lives behind a coarse pointer. It sits here, in the one stylesheet
   every page loads, so a page can't forget it. `!important` because the page
   rules it corrects are often three classes deep; it only ever RAISES a size.

   1. Fields → 48px, text buttons / pills / chips / toggles → 44px. min-height,
      not height, so a control that is already taller keeps its height.
   2. Small icon closes (×) keep their LOOK — enlarging every corner circle
      would make every panel heavy — and get an invisible 44px tap area. */
@media (hover: none) and (pointer: coarse) {
  /* 1a. fields */
  .field-input, .suggest-input, .claim-input, .import-card-input,
  .import-search, .add-when-input, .portfolio-link-input {
    min-height: 48px !important;
  }
  /* 1b. text buttons, pills, chips, toggles */
  .provider-btn, .btn-primary, .btn-ghost,
  .import-card-btn, .import-pill,
  .detail-pill-trigger, .detail-sentiment, .detail-signup-cta, .detail-review-btn,
  .add-date-chip, .add-love-toggle, .sheet-opt, .sheet-clear-btn,
  .header-follow-btn, .lc-btn, .video-row-btn, .settings-upgrade-btn,
  #undoToastBtn, .cat-chip, .theme-toggle, .import-chip {
    min-height: 44px !important;
  }
  .theme-toggle, .video-row-btn { min-width: 44px !important; }

  /* 2. icon closes: same look, 44px hit area. ::after is free on every one of
     these (checked). The static ones need a positioning context for it. */
  .claim-close, .import-hd-close, .nav-search-close, .cat-clear-trigger {
    position: relative;
  }
  .settings-hd-close::after, .claim-close::after, .import-hd-close::after,
  .nav-search-close::after, .video-theater-close::after, .cat-clear-trigger::after {
    content: ""; position: absolute; top: 50%; left: 50%;
    width: 44px; height: 44px; transform: translate(-50%, -50%);
  }
  /* The circular top-right closes are sized in the CLOSE BUTTONS block below. */
}

/* ── CLOSE BUTTONS: ONE × (Kyle 2026-09-22: "make them all consistent size and
   weight… top right x's they all shift in design and size"). There were seven
   sizes (26/28/30/34/36/40/44), five glyph sizes (10–16px) drawn three ways
   (an SVG, .icon-x bars, and one literal "×" character). Now every top-right
   close is:
     · a 36px circle with a 1px border (40px on touch)
     · a 12px × at a 1.5px stroke, however it happens to be drawn
     · rotating 90° on hover, where there is hover
   Colour stays per context — a PANEL close is an outline on the panel, a close
   FLOATING over artwork keeps its dark glass — because those sit on different
   grounds; size and weight are what must not vary. `html` prefix = one class of
   specificity over every page's own rule, so each page's rule keeps its colour
   and position but can no longer set the size. A NEW close joins this list. */
html .settings-hd-close, html .import-hd-close, html .claim-close, html .add-modal-close,
html .detail-close, html .detail-trailer-close, html .tshare-close,
html .video-theater-close, html .privacy-close, html .search-results-close {
  width: 36px; height: 36px; border-radius: 50%; border-width: 1px; border-style: solid;
  box-sizing: border-box; padding: 0; --icon-x-size: 12px;
  /* NO display here, on purpose: this rule outranks each page's own, so setting
     display overrode the phone rule that HIDES the search-results × (it showed
     up on phones, top-left — inline-flex also ignores the auto margin that
     right-aligns it). Every close already centres its glyph itself. */
  transition: transform 0.25s cubic-bezier(0.22, 1, 0.36, 1), color 0.15s, background 0.15s, border-color 0.15s;
}
/* The search-results close overlays the list with a negative bottom margin equal to its height. */
html .search-results-close { margin-bottom: -36px; }
/* Panel closes that had no ring (the add modal) get the panel outline. */
html .add-modal-close { border-color: var(--border-hi, rgba(255,255,255,0.14)); }
/* The trailer close had no ring either; it floats over video, so it takes the glass. */
html .detail-trailer-close { background: rgba(10,9,9,0.55); border-color: rgba(255,255,255,0.18); }
/* SVG-drawn ×: a 10-unit viewBox at 12px renders the 1.2 stroke at ~1.44px, i.e. the same weight as the 1.5px bars. */
html .settings-hd-close svg, html .import-hd-close svg, html .claim-close svg { width: 12px; height: 12px; }
/* Bar-drawn × (own ::before/::after rather than .icon-x): same 12 × 1.5. */
html .detail-trailer-close::before, html .detail-trailer-close::after,
html .tshare-close::before, html .tshare-close::after,
html .privacy-close::before, html .privacy-close::after { width: 12px; height: 1.5px; }
@media (hover: hover) {
  html .settings-hd-close:hover, html .import-hd-close:hover, html .claim-close:hover, html .add-modal-close:hover,
  html .detail-close:hover, html .detail-trailer-close:hover, html .tshare-close:hover,
  html .video-theater-close:hover, html .privacy-close:hover, html .search-results-close:hover { transform: rotate(90deg); }
}
@media (hover: none) and (pointer: coarse) {
  html .settings-hd-close, html .import-hd-close, html .claim-close, html .add-modal-close,
  html .detail-close, html .detail-trailer-close, html .tshare-close,
  html .video-theater-close, html .privacy-close, html .search-results-close {
    width: 40px; height: 40px;
  }
}

/* Menu + Settings icons on phones (Kyle 2026-09-22: "icons in the settings menu
   are too small on mobile"). The account-menu icons were drawn at 14px and the
   Settings theme toggle's at 12px — sized for the 12px desktop label. On touch the
   label is 14px, so the icons step up to stay in proportion with it: 18px in the
   menu, 16px in the theme toggle. SVGs scale cleanly; stroke weights scale with them. */
@media (hover: none) and (pointer: coarse) {
  html .acct-menu-item svg { width: 18px; height: 18px; }
  html .acct-menu-item { gap: 12px; }
  html .settings-theme-opt svg { width: 16px; height: 16px; }
}

/* Bottom-rail icons on phones (Kyle 2026-09-22: "the icons in the bottom nav on
   library are too small on mobile"). The circles grew to 48px on touch but the
   view icon stayed 11px — a quarter of its button. One scale for the rail:
   solid view icons 16px, the magnifier 21px, outline
   icons 20px (thin strokes need the extra size to carry the same weight). */
@media (hover: none) and (pointer: coarse) {
  html .global-sort-trigger .view-icon { width: 18px; height: 18px; }
  /* 21px, not 18: the magnifier's glyph only fills ~78% of its 20-unit viewBox,
     so at 18px it read smaller than the solid 16px view icon (Kyle 2026-09-22). */
  html .nav-search-open svg, html .nav-search-row .nav-search-icon { width: 21px; height: 21px; }
  html .res-view-toggle svg { width: 20px; height: 20px; }
}

/* Shelf share + copy-link icons on phones (Kyle 2026-09-22: "the share and link
   icons on mobile seem too small now, should match the settings icon sizes").
   Same 18px as the account-menu icons, in the shelf header AND the sort sheet's
   Share / Copy link rows. The paper plane fills its viewBox, so it runs 1px
   under (17) to read the same size — the desktop 12/13 ratio. The header box
   grows to 32px and the last one still hangs out by its empty half
   ((32 − 18) / 2 = 7px) so the GLYPH sits on the header's text margin. No
   display here — edit mode hides these with display:none. */
@media (hover: none) and (pointer: coarse) {
  html .cat-share-link { width: 32px; height: 32px; margin-left: 6px; }
  html .cat-share-link:last-child { margin-right: -7px; }
  html .cat-share-send + .cat-share-link { margin-left: 0; }
  html .cat-share-link svg { width: 18px; height: 18px; }
  html .cat-share-send svg { width: 17px; height: 17px; }
  html .sheet-share-btn svg { width: 18px; height: 18px; }
}

/* Detail window × + back on the eyebrow/icon line (Kyle 2026-09-22: "the top
   right x on details now missaligns optically to the other icons and the
   eyebrow"). The top row was laid out for a 30px circle: eyebrow, icons and ×
   all 30px tall at top:14px, so their centres met 29px down. The × grew to 36
   (40 on touch) but kept top/right 14, so its centre dropped 3px (5 on touch)
   and moved 3px (5) in from the edge. Pulling it up and out by half the growth
   puts its centre back on the line and in its old spot. The back button mirrors
   the × top-left, so it takes the same size and offset. */
html .detail-back { width: 36px; height: 36px; box-sizing: border-box; }
html .detail-close, html .detail-back { top: calc(11px + env(safe-area-inset-top, 0px)); }
html .detail-close { right: 11px; }
html .detail-back { left: 11px; }
@media (hover: none) and (pointer: coarse) {
  html .detail-back { width: 40px; height: 40px; }
  html .detail-close, html .detail-back { top: calc(9px + env(safe-area-inset-top, 0px)); }
  html .detail-close { right: 9px; }
  html .detail-back { left: 9px; }
}

/* ── ONE LINE WEIGHT FOR EVERY LINE ICON (Kyle 2026-09-22: "the icons in settings
   seem to all have slightly different line widths… all line widths need to be
   consistent and match the icons on the library page… lets make these icons
   site wide. also the trailer"). The icons were drawn in five viewBoxes
   (6/9/10/14/16/20/24) with stroke-widths from 1 to 2.2, then shown at 9-21px,
   so the drawn line ran anywhere from ~0.7 to ~1.9px, and some paths had round
   caps while others were square or butt. Rather than redraw each one,
   non-scaling-stroke makes stroke-width a real screen-pixel value whatever the
   viewBox or display size, so every line is identical: 1.3px on desktop (what
   the shelf share/link icons draw at 13px) and 1.8px on touch (their weight at
   18px). Caps and joins go round across the set.
   SCOPE: stroked shapes (a stroke attribute on the shape or on its <svg>)
   inside anything you can tap — buttons, links, menu items — plus the saved
   ticks and the tile map pin. Fill-only parts (the Help dot, play triangles,
   the speaker body, stroke="none") are untouched.
   KEPT OUT ON PURPOSE: the × closes (their own 1.5px spec above), the verdict
   glyphs (hearts and thumbs draw with the stars, not with the icons) and the
   score rings (a 3-unit data ring, not a line icon). */
html :is(button, a, [role="button"], [role="menuitem"], .detail-saved, .saved-pop, .nav-search-row)
  :is(path, circle, rect, line, polyline, polygon, ellipse):is([stroke], svg[stroke] *):not([stroke="none"], .score-ring *, :is(.settings-hd-close, .import-hd-close, .claim-close, .nav-search-close, .tile-heart, .add-love-toggle, .sent-heart, .sent-thumb) *),
html .tile-map-link svg :is(path, circle, rect, line, polyline, polygon, ellipse) {
  vector-effect: non-scaling-stroke;
  stroke-width: 1.3px;
  stroke-linecap: round;
  stroke-linejoin: round;
}
@media (hover: none) and (pointer: coarse) {
  html :is(button, a, [role="button"], [role="menuitem"], .detail-saved, .saved-pop, .nav-search-row)
    :is(path, circle, rect, line, polyline, polygon, ellipse):is([stroke], svg[stroke] *):not([stroke="none"], .score-ring *, :is(.settings-hd-close, .import-hd-close, .claim-close, .nav-search-close, .tile-heart, .add-love-toggle, .sent-heart, .sent-thumb) *),
  html .tile-map-link svg :is(path, circle, rect, line, polyline, polygon, ellipse) {
    stroke-width: 1.8px;
  }
}

/* Detail controls backdrop reaches ABOVE the review (Kyle 2026-09-22: "with our
   taller buttons, on detail pages, the add a review… is disappearing, the
   gradient behind it needs to move further up… on mobile especially"). The fade
   was sized in PERCENT of (controls + 96px), so when the buttons grew to 44-48px
   the whole ramp stretched and the review line, at the TOP of the controls, sat
   in the half-transparent middle of it, over the scrolling synopsis. It's
   measured in pixels from the top edge now: a 120px fade that finishes just
   above the controls, then solid behind everything in them, whatever their
   height. Same stops as before, just in px. Both themes, all three pages
   (discover/resonance carry identical copies of the rule this overrides). */
html .detail-controls::before {
  top: -120px;
  background: linear-gradient(to bottom,
    rgb(var(--dc-fade, 0 0 0) / 0) 0, rgb(var(--dc-fade, 0 0 0) / 0.02) 10px,
    rgb(var(--dc-fade, 0 0 0) / 0.07) 22px, rgb(var(--dc-fade, 0 0 0) / 0.16) 36px,
    rgb(var(--dc-fade, 0 0 0) / 0.28) 50px, rgb(var(--dc-fade, 0 0 0) / 0.42) 64px,
    rgb(var(--dc-fade, 0 0 0) / 0.57) 78px, rgb(var(--dc-fade, 0 0 0) / 0.72) 90px,
    rgb(var(--dc-fade, 0 0 0) / 0.84) 101px, rgb(var(--dc-fade, 0 0 0) / 0.93) 111px,
    rgb(var(--dc-fade, 0 0 0) / 0.98) 120px, rgb(var(--dc-fade, 0 0 0) / 1) 132px,
    rgb(var(--dc-fade, 0 0 0) / 1) 100%);
}
html body.theme-light { --dc-fade: 240 237 232; }

/* Trailer × follows the detail × (Kyle 2026-09-22). Same 36/40 circle, same
   "half the growth" offset, so the two sit in the identical spot. */
html .detail-trailer-close { top: calc(11px + env(safe-area-inset-top, 0px)); right: 11px; }
@media (hover: none) and (pointer: coarse) {
  html .detail-trailer-close { top: calc(9px + env(safe-area-inset-top, 0px)); right: 9px; }
}

/* Rating pill on phones: the avatar is bigger, and the row stays CENTRED.
   Kyle 2026-09-22 asked for a larger avatar and tried avatar-left / verdict-right,
   then: "i'm ok with the larger profile photo but lets center that top button as
   it was, my left and right aligned stuff looks weird". So only the size change
   stays: the avatar (the pill's first child, photo or initial) goes 20 → 30px,
   the size of the stars and heart beside it. The pill keeps its centred layout. */
@media (max-width: 719px) {
  html .detail-controls .detail-sentiment > :is(.sent-avatar, .sent-avatar-initial):first-child {
    width: 30px; height: 30px; font-size: var(--fs-label, 12px);
  }
}

/* WHEN, redesigned (Kyle 2026-09-22: "this month this year earlier type now
   looks too small on mobile… maybe under the calendar, and only have 3 and make
   them pills not squares"). The date field is the real answer, so it leads; the
   quick picks become three shortcuts under it, as pills that share the row
   equally, at label size rather than the eyebrow size four squares needed to
   fit. "Earlier" is gone (JS): it stamped Jan 1 of LAST year, a made-up date,
   and the field now sitting first does that job properly. Scoped with :has()
   to the section that holds the chips — the review section shares the class. */
html .detail-when-section:has(> .add-date-chips) { display: flex; flex-direction: column; }
html .detail-when-section:has(> .add-date-chips) > :is(.add-when-input, .add-when-wrap) { order: 1; margin: 0; }
html .detail-when-section > .add-date-chips { order: 2; margin: 10px 0 0; gap: 8px; flex-wrap: nowrap; }
html .detail-when-section .add-date-chip { flex: 1 1 0; min-width: 0; height: 40px; padding: 0 10px; border-radius: 999px; }
html .detail-when-section .add-date-chip span { font-size: var(--fs-label, 12px); white-space: nowrap; letter-spacing: 0.02em; }

/* Detail page rhythm on phones (Kyle 2026-09-22: "spacing for mobile, detail
   pages is now too tight"). The phone type scale stepped every size up ~+2px
   (about 15%), but the gaps between them stayed at their desktop values, so the
   page read cramped. The gaps grow by the same proportion: fact rows 16 → 22,
   label-to-value 5 → 7, synopsis/scores/facts sections 18 → 24, and the scores
   grid matches the facts grid it sits over. Same condition as the type step. */
@media (pointer: coarse) and (max-width: 600px), (pointer: coarse) and (max-height: 500px) {
  html .detail-facts { row-gap: 22px; margin-top: 24px; }
  html .detail-fact-k { margin-bottom: 7px; }
  html .detail-scores-row { row-gap: 22px; margin-top: 24px; }
  html .score-cell { gap: 7px; }
}

/* Shelf headers the same height as the header and jump strip on phones (Kyle
   2026-09-22: "i'd prefer if the shelf headers matched what i see for the
   header and subnav"). The site header and jump strip are 44px
   (--bottom-h / --jumpnav-h). The shelf header was 11px padding + content,
   and once the share/link icons grew to 32px boxes that became ~54px, a
   visibly taller band than the two above it. Now it's a 44px row with its
   content centred; the 32px icons and edit mode's 28px buttons both fit
   inside it. */
@media (pointer: coarse) and (max-width: 600px), (pointer: coarse) and (max-height: 500px) {
  html .cat-header { padding-top: 0; padding-bottom: 0; min-height: var(--jumpnav-h, 44px); }
}

/* Rail icons redrawn as LINE icons (Kyle 2026-09-22: "the search and the 3
   icons to show the library view now seem too thick compared to the rest of the
   website's icons"). The magnifier was a filled ring about 2px thick at 21px,
   and the grid/list/artwork view icons were solid blocks, so both read heavier
   than the 1.3/1.8px line set. Now they're stroked outlines (stroke attributes)
   and pick up the one-line-weight rule above like every other icon. Outlines
   need a little more room than solid blocks, so the view icon is 13px on
   desktop (was 11) and 18px on touch (was 16). The magnifier keeps its size;
   the new drawing fills the box about as much as the old one did. */
html .global-sort-trigger .view-icon { width: 13px; height: 13px; }
@media (hover: none) and (pointer: coarse) {
  html .global-sort-trigger .view-icon { width: 18px; height: 18px; }
}

/* Feed bylines on phones: a sizing exception (Kyle 2026-09-22: "activity in
   mobile is hard to read, did we make the names and ratings larger too?"). Yes:
   the byline rides --fs-caption, which the phone scale took from 11 to 13, and
   its stars rode --fs-eyebrow (10 → 12). The byline is a 3-column row inside a
   44vw tile (~172px on an iPhone) that was measured to fit "@kylelamar ★★★★★ ❤️"
   at 11px. At 13px the handle collapsed to "@kylela…". So the byline takes
   ONE step up on phones instead of two: 12px text (the phone eyebrow token's
   value) and 11px glyphs (glyphs aren't tokens). Budget at 12px: 10px padding
   ×2 + 66px handle + 7px gaps ×2 + ~62px stars+heart ≈ 164px, which fits. Covers
   the Activity and Discover feeds and the detail window's shelves (the same
   component). */
@media (pointer: coarse) and (max-width: 600px) {
  html :is(.activity-byline, .tonal-shelf-byline) { font-size: var(--fs-eyebrow); }
  html :is(.activity-byline, .tonal-shelf-byline) .by-rate :is(.s-stars, .s-emo) { font-size: 11px; }
}

/* View icons, round 2 (Kyle 2026-09-22): at the shared line weight the grid
   squares and artwork columns nearly touched, and the list icon's outlined
   squares were too tight. Redrawn with the gaps opened up: grid squares 4.8
   units with a 4.4 gap, artwork columns 2.6 wide with a 3.1 gap. The list
   bullets are now DOTS: zero-length strokes with round caps, so each dot is
   exactly the line weight, the same thickness as the lines beside it. Drawn
   a size up to give the gaps room: 14px desktop, 20px touch (~2.2 / ~3.7px
   of clear space between shapes at 1.8px lines). */
html .global-sort-trigger .view-icon { width: 14px; height: 14px; }
@media (hover: none) and (pointer: coarse) {
  html .global-sort-trigger .view-icon { width: 20px; height: 20px; }
}

/* Menu icons at one OPTICAL size (Kyle 2026-09-22, on his phone: "if the share
   paper plane icon is the standard size, then that one feels optically larger
   than the rest, so all other icons need scaled up slightly to match"). The
   plane fills ~80% of its box; the circle-based icons (Help, Discover, Sign
   out…) fill ~75%, so at the same box size they read smaller. Everything steps
   up by that ratio (18 → 19 on touch, 14 → 15 desktop). The plane stays at 18/14
   because it IS the reference. The gear stays at 18/14 because its redrawn
   5-tooth outline fills ~82%, already level with the plane. Non-scaling stroke
   keeps the line weight identical whatever the box size. */
html .acct-menu-item svg { width: 15px; height: 15px; }
html #acctMenuShareCard svg, html #acctMenuSettings svg { width: 14px; height: 14px; }
@media (hover: none) and (pointer: coarse) {
  html .acct-menu-item svg { width: 19px; height: 19px; }
  html #acctMenuShareCard svg, html #acctMenuSettings svg { width: 18px; height: 18px; }
}

/* Header Follow button on phones (Kyle 2026-09-22: "the follow button is too
   tall for the header"). The touch rule above lifted .header-follow-btn to a
   44px min-height, which is the header's full height, so the pill touched both
   edges. In the header it draws at 32px (6px of air above and below in the
   44px bar) and keeps a 44px tap area through an invisible ::after. The same
   class on People-list rows keeps the full 44px, since those rows have room. */
@media (hover: none) and (pointer: coarse) {
  html #followBtn { min-height: 0 !important; height: 32px; position: relative; }
  html #followBtn::after { content: ""; position: absolute; left: 0; right: 0; top: -6px; bottom: -6px; }
}

/* Score rings at the standard control size (Kyle 2026-09-22: "make our ratings
   circles match our (standard) button and ui sizes between desktop and mobile…
   they all appear slightly too small… the type is fine"). They were 26px, a
   size nothing else uses. Now they're the same circle as the × closes and small
   round controls: 36px on desktop, 40px on touch. The line is set in viewBox
   units, 2.2 (the ring's viewBox is 36, so that's 2.2px on desktop and ~2.4px
   on touch). NOT non-scaling-stroke: that would put the dash pattern in screen
   space, and the count-up fill's dasharray is computed in viewBox units. */
html .score-ring { width: 36px; height: 36px; }
html .score-ring circle { stroke-width: 2.2; }
@media (hover: none) and (pointer: coarse) {
  html .score-ring { width: 40px; height: 40px; }
}
}

/* Edit-mode ↑ ↓ match the × beside them (Kyle 2026-09-22: "the up and down
   buttons are larger than the x is really the only issue"). The touch rule had
   grown the reorder buttons to 44px squares while the clear × kept its 28px
   bordered square with an invisible 44px tap area. The reorder buttons now use
   the × approach: they stay 28px and get the same invisible 44px ::after. */
@media (hover: none) and (pointer: coarse) {
  html .row-move-btn { position: relative; }
  html .row-move-btn::after { content: ""; position: absolute; left: 50%; top: 50%; width: 44px; height: 44px; transform: translate(-50%, -50%); }
}

/* Connect & upload brought in line with Settings and the rest of the site
   (Kyle 2026-09-22: "please review the type buttons, pills forms etc for
   mobile / desktop and match our styles"):
   · Intro copy (.import-sub) uses --fs-label, the Settings description voice
     (it was one step up, --fs-ui, so on a phone it read louder than every
     other panel's copy).
   · Category chips (.import-chip) are the site's filter pill: 44px on touch
     (the list above), with label-size text and room either side.
   · Search field is the Settings field: 48px, with a real 16px font drawn at
     0.875 (= 14px) so it matches the copy and iOS still doesn't zoom.
   · Continue is the panel's primary button, 48px on touch like Settings' Done. */
html .import-sub { font-size: var(--fs-label); }
@media (hover: none) and (pointer: coarse) {
  html .import-chip { font-size: var(--fs-label); padding: 0 16px; }
  html .import-search {
    font-size: 16px; height: 54.857px;
    width: calc(100% / 0.875); margin-right: calc(100% - 100% / 0.875);
    margin-bottom: -6.857px; transform: scale(0.875); transform-origin: top left;
  }
  html .import-continue { height: 48px; font-size: var(--fs-ui); }
}

/* Loader lines in sentence case (Kyle 2026-09-22: "for all of the loaders, we
   are using all caps… i'd prefer a simple Sentence case in those moments that
   match our titles on the library, activity, discover… can still be a quiet
   color"). The boot line ("Loading @x's library"), the feed scan ("Gathering
   your feed"), the search gem ("Searching") and the import scan's "things
   connected" all drop the tracked caps for the shelf-title voice: --fs-label,
   0.03em, no transform. Each keeps its own quiet colour and opacity. */
html :is(.profile-boot-status, .feed-scan-status, .search-loading-label, .import-scan-total-label) {
  text-transform: none; letter-spacing: 0.03em; font-size: var(--fs-label);
}

/* Taller header + subnav, bigger URL, on phones (Kyle 2026-09-22: "the
   tonal.cc/kylelamar/activity now seems too small compared to the subnav… with
   the new height of text we may just want to move the header and subnav to be
   a little taller… library, activity, discover (mobile)"). The phone type step
   put the subnav pills at 16px, but the serif URL stayed at its desktop 18px
   (a condensed face, so it reads smaller than its number) inside 44px bars
   sized for the old type. Now:
   · both bars are 52px: the library's --bottom-h / --jumpnav-h, the feeds'
     --header-h / --discnav-h. Every offset (sticky tops, scroll margins, the
     jump strip's position, main's padding) already reads these variables, and
     the library's shelf headers follow --jumpnav-h, so they stay matched.
   · the URL breadcrumb goes 18 → 22px.
   `html:root` out-ranks each page's own :root declaration. */
@media (pointer: coarse) and (max-width: 600px) {
  html:root { --bottom-h: 52px; --jumpnav-h: 52px; --header-h: 52px; --discnav-h: 52px; }
  html :is(.header-url, .header-url-base, .header-url-current) { font-size: 22px; }
}

/* ── ONE LINK LINE, SITE-WIDE (Kyle 2026-09-22: "terms and privacy policy have
   a thicker link line than the above, they should match (all link lines
   site-wide should match)"). Text links were drawn three ways: a 1px
   border-bottom at 10% white (the auth doors), a border-bottom at --border-hi
   with 2px padding (the doc pages), and text-decoration underlines in either
   currentColor (the legal line, the thick one) or --border-hi (detail
   credits). --border-hi itself differs per page (0.13 to 0.18). Now every
   inline text link is the same line: a 1px underline, 3px below the text, at
   --link-line (20% of the text colour's opposite ground), rising to the text
   colour on hover. Border-drawn links lose their border for it.
   !important only on the decoration properties: some links carry them inline. */
:root { --link-line: rgba(255,255,255,0.2); }
body.theme-light { --link-line: rgba(0,0,0,0.2); }
html :is(
  .auth-mode-switch a, .auth-alt-action a, .field-forgot, .auth-legal a, .auth-sub a,
  .sent-link, .auth-status a, .back-link button, .signin-line a,
  .detail-credit-link, .import-card-clientid-help a, .import-card-upload-note a,
  .import-skip, .import-suggest a, .import-empty a,
  .settings-change-link, .settings-username-change, .settings-cancel-link,
  #settingsOpenConnect, .sg-connect
),
html body[data-footer="pinned"] :is(section p a, .contact a, .lede a, .qa .a a) {
  border-bottom: 0; padding-bottom: 0;
  text-decoration-line: underline !important;
  text-decoration-thickness: 1px !important;
  text-underline-offset: 3px !important;
  text-decoration-color: var(--link-line) !important;
}
html :is(
  .auth-mode-switch a, .auth-alt-action a, .field-forgot, .auth-legal a, .auth-sub a,
  .sent-link, .auth-status a, .back-link button, .signin-line a,
  .detail-credit-link, .import-card-clientid-help a, .import-card-upload-note a,
  .import-skip, .import-suggest a, .import-empty a,
  .settings-change-link, .settings-username-change, .settings-cancel-link,
  #settingsOpenConnect, .sg-connect
):hover,
html body[data-footer="pinned"] :is(section p a, .contact a, .lede a, .qa .a a):hover {
  text-decoration-color: currentColor !important;
}
/* Hover-only underlines (feed sub-links, people handles, score sources) take
   the same weight and offset when they appear. */
html :is(.disc-section-sub .sub-btn, .people-main .people-handle, .detail-k-src, .detail-lyr-src):hover {
  text-decoration-thickness: 1px; text-underline-offset: 3px;
}

/* Doc pages (FAQ, Privacy, What's new) on phones (Kyle 2026-09-22):
   · "Help & frequently asked questions doesn't need to appear so low": the
     page's 56px top padding was sized for desktop. The pinned × sits top-right,
     clear of the left-set title, so 24px is enough.
   · "can we have the numbers appear left of the titles… rather than stack?":
     below 540px the 01/02 number used to drop onto its own line above the
     section title. It now sits beside the title on a shared baseline. The
     section is a 2-column grid for the number and title only; every other child
     spans the full width. */
@media (max-width: 540px) {
  html body:has(.privacy-close) .wrap { padding-top: 24px; }
  html body:has(.privacy-close) section:has(> .sec-num) { display: grid; grid-template-columns: auto minmax(0, 1fr); column-gap: 12px; }
  html body:has(.privacy-close) section:has(> .sec-num) > * { grid-column: 1 / -1; }
  html body:has(.privacy-close) section > .sec-num { grid-column: 1; margin: 0; align-self: baseline; }
  html body:has(.privacy-close) section > .sec-num + h2 { grid-column: 2; align-self: baseline; }
}
