/*
================================================================================
  ML Software, LLC
  Copyright 2026. All rights reserved.

  Life IQ | lifeiq.mlsoftware.com

  assets/css/product.css

  Platform: IQ Platform
  Version : 1.71.0
  Created : 2026-07-22
  Updated : 2026-08-05

  Description: LifeIQ component styles. Everything here is prefixed liq-
  so a glance at a class name says whether it is platform or product.

  Sizing is mobile-first and deliberate. Body copy is 15px because this
  app gets read at 6am without glasses. Every tappable thing is at least
  44px tall. Nothing relies on hover, because on the device this is
  built for there is no hover.

  Loads after theme.css (which defines the signal and dragon palettes)
  and before mobile-tabs.css (which overrides shell layout on touch).

  Version History:
    1.71.0 - 2026-08-05 - Subtask chevron glyph enlarged. The 44px target
                         was already right; the 14px triangle inside it
                         was not, so the only way into the subtask panel
                         read as a speck.
                         Spinner for the day-open and day-close buttons
                         (checkin.js 1.4.0).
    1.70.0 - 2026-08-05 - Effort picker goes four across for eight rungs
                         (tasks.js 2.25.0). Eight divides into two clean
                         rows of four; the three-column grid would have
                         left two orphans on a third row.
    1.69.0 - 2026-08-05 - Subtask panel rebuilt: drag handle, effort
                         select and delete per step, a total line, and a
                         wider add row. .liq-sub-title.done is replaced
                         by .liq-sub.is-done so the whole row dims
                         together rather than the text alone.
                         Needs tasks.js 2.23.0.
    1.68.0 - 2026-08-05 - Subtask chevron is a real target and shows a
                         count; subtask lines render on Today.
                         The chevron was a 14px glyph in 4px of padding
                         - about 22px square, half the touch floor - on
                         the only control that opens the subtask panel.
    1.67.0 - 2026-08-05 - The pair becomes ONE capsule: importance left,
                         duration right, one border, one divider. Two
                         adjacent shapes had to be memorised; a position
                         inside one object is learned once.
                         Duration segment is fixed width so the divider
                         does not wander down the column - "15m" is
                         wider than "1h" and a ragged internal line
                         makes a list feel noisy for no nameable reason.
                         Needs tasks.js 2.21.0.
    1.66.0 - 2026-08-05 - Worth and cost sit adjacent in one cell, both
                         bigger, cost now a chip matching worth's shape.
                         Row drops to six tracks. Today draws the same
                         pair.
                         Also fixes a real bug: .liq-task.is-done
                         .liq-check styled the filled checkmark and the
                         row emits .liq-task.done - so a completed task
                         on Tasks struck its title through and left the
                         circle empty. The title rule had both spellings
                         and the check rule had one.
    1.65.0 - 2026-08-05 - Cost is a numeral, not a dial, and the two
                         marks swap places - worth reads before cost.
                         The dial was fine at desk size and a smudge on
                         a phone. Grid track order follows: the fixed
                         32px importance track moves ahead of the
                         auto-width duration one. Needs tasks.js 2.19.0.
    1.64.0 - 2026-08-05 - Worth is a numbered chip, cost is a dial
                         (tasks.js 2.18.0). The importance dots and the
                         six-bar effort ladder are both gone - two
                         rising ladders in one row was why neither could
                         be told from the other. There is now exactly
                         one filling shape on screen and it is the
                         quieter of the two marks.
    1.63.0 - 2026-08-05 - .iq-dt tracks are equal thirds for BOTH the date
                         and time variants, and the :has() rule that
                         split them is gone. One rule instead of two,
                         and no reliance on a selector whose support I
                         would rather not be depending on for something
                         this basic. "Sep" and "2026" both fit an equal
                         third at 16px; the uneven ratios were solving a
                         problem that the padding fix had already
                         solved.
    1.62.0 - 2026-08-05 - Mood scale is red, amber, grey, BLUE, green.
                         +1 and +2 were both green, so the top half of a
                         five point scale was a four point scale with a
                         duplicate - the one place the scale most needs
                         to be readable is the good end, because that is
                         where the difference between fine and genuinely
                         good lives. Changed in both places at once, the
                         sheet and the Today row.
    1.61.0 - 2026-08-05 - The From/To picker actually widens now. .iq-dt is
                         a grid container used as a flex item and had no
                         flex-grow, so it sized to content and the three
                         tracks divided a box that was never given any
                         width. Also: the time variant now gets equal
                         tracks instead of the date variant's ratios.
                         1.60.0 edited .liq-when-h/m/ap, which match
                         NOTHING - Reality uses IQ.dt.timeSelect and
                         those classes are leftovers from the markup it
                         replaced. Deleted rather than left to mislead
                         the next person. The padding fix in 1.60.0 was
                         real and stands.
    1.60.0 - 2026-08-05 - Reality's From/To selects: the padding SHORTHAND
                         bug again, in the second and last place it
                         lives. .liq-when-row is its own markup, not
                         IQ.dt, so the 1.44.0 fix never reached it. Row
                         also widened - the label track was taking 46px
                         from three controls that needed it.
    1.59.0 - 2026-08-05 - Inline mood row on Today (today.js 2.11.0).
    1.58.0 - 2026-08-05 - Delete control on the Reality edit form
                         (reality.js 1.3.0).
    1.57.0 - 2026-08-05 - Opener chip. The morning read is offered rather
                         than painted into every new conversation.
                         Needs wingman.js 2.8.0, Checkin.cfc 2.4.1.
    1.56.0 - 2026-08-05 - Wingman header lost its inherited 22px top
                         margin and baseline alignment; composer box
                         opens at two rows. Needs wingman.js 2.7.1.
    1.55.0 - 2026-08-05 - Wingman becomes a column that fills the
                         viewport: header, scrolling message list,
                         composer. 1.53.0 and 1.54.0 are REVERTED - both
                         were sticky-positioning patches on the page
                         scroller, and the approach was wrong rather
                         than the numbers. Needs wingman.js 2.7.0.
    1.54.0 - 2026-08-05 - Wingman header pinned. Reverted in 1.55.0.
    1.53.0 - 2026-08-05 - Composer background bleed. Reverted in 1.55.0.
    1.52.0 - 2026-08-05 - .iq-content could not scroll. min-height: 0 on
                         the two shell grid items that own an
                         overflow-y. Platform bug; overridden here, and
                         it belongs in the bundle.
    1.51.0 - 2026-08-05 - Drawer toggle glyph optically centred. Product
                         override, not a shell.css edit - see the note
                         on the rule.
    1.50.0 - 2026-08-05 - Wingman conversations sheet (wingman.js 2.6.0).
    1.49.0 - 2026-08-04 - Amber ring moved from .is-today to .is-open.
                         It marks a day that has been started and not
                         finished, on any cell in the strip, rather than
                         marking which cell is today. .is-today now
                         carries no colour at all - it only decides
                         whether the cell is a button.
    1.48.0 - 2026-08-04 - Streak strip: fill and ring became independent
                         signals. Blue fill means the day was closed;
                         an amber ring means that cell is today. They
                         stack, so a closed today is a blue cell with an
                         amber ring and needs no third state.
                         This removes the reason the strip's direction
                         mattered. Today was previously findable only by
                         a 1px dashed-versus-solid difference on a 14px
                         square, so the only way to locate it was to
                         know which end the strip ran from. A ring in a
                         colour used nowhere else on the row is legible
                         reading either way, and the question of which
                         end is today stops being a question.
    1.47.0 - 2026-08-04 - Time-log sheet for a just-completed task
                         (today.js 2.8.0). Its own block rather than
                         reusing .liq-mood-*: the two sheets look alike
                         today and will not stay that way, and a rule
                         named for moods quietly governing task time is
                         how a stylesheet stops being readable.
    1.46.0 - 2026-08-04 - Dragon mark from 18px to 34px. One rule was
                         sizing it in the hero card AND in list rows,
                         so the size that fit a row was the size the
                         card got - an orange blob beside the only
                         heading on the screen that matters. Split: 34px
                         in the card, 26px in a row.
    1.45.0 - 2026-08-04 - Effort is six rungs. Sixth bar, taller ladder,
                         and the picker drops the orphan-span rules -
                         six buttons fill two rows of three cleanly.
    1.44.0 - 2026-08-04 - IQ.dt caret sat on the text: .iq-dt .form-input
                         used the padding SHORTHAND, wiping the 40px
                         padding-right forms.css sets to clear the
                         chevron. All four sides declared, chevron moved
                         in, tracks uneven so the day list stops taking
                         width from the month and year.
                         Effort scale. Task row grid to seven tracks;
                         .liq-effort bars and the .liq-eff-pick word
                         picker. The .liq-diff-* rules are now dead
                         and stay until the difficulty column drops.
    1.43.0 - 2026-08-04 - IQ.dt dropdowns and the task difficulty picker.
    1.42.0 - 2026-08-03 - Time entry dropdowns on the log form.
    1.41.0 - 2026-08-03 - Quotes back button is a real target: 88x48 with
                          a border and a word, not a 24px chevron.
    1.40.0 - 2026-08-03 - Condition rows take three options, not two.
    1.39.0 - 2026-08-03 - Wingman composer is a column: full-width
                          textarea over the buttons. Sharing a row with
                          two buttons left it a thumb wide and one line
                          tall.
    1.38.0 - 2026-08-03 - Mood scale inside the day read; moment bar gone.
    1.37.0 - 2026-08-03 - Composer buttons no longer grow with the
                          textarea. Both the composer row and the nested
                          button row defaulted to align-items:stretch, so
                          Plan and Send matched the message height. The
                          textarea also scrolls at its cap instead of
                          hiding text, and is 16px so iOS stops zooming
                          the page on focus.
    1.36.0 - 2026-08-03 - Saying conditions block.
    1.35.0 - 2026-08-03 - Pulse sheet, and the wordmark as a button.
    1.34.0 - 2026-08-03 - Sayings screen: buckets, list, editor, rotation.
    1.33.0 - 2026-08-03 - Attribution line under Wingman's opener.
    1.32.0 - 2026-08-03 - Morning-read styles removed; the read is off
                          Today entirely.
    1.31.0 - 2026-08-03 - Morning read collapsed and attributed. It was
                          an unlabelled block of text at the top of
                          Today with no clue what it was.
    1.30.0 - 2026-08-03 - Streak strip and the sayings editor.
    1.29.0 - 2026-08-03 - Mood sheet and the mood button, replacing the
                          bad-day flag.
    1.28.0 - 2026-08-03 - Goal metric: bar, pace line, vague nudge and
                          the metric fields on the add form. Sits with
                          the rest of the goal styles rather than in a
                          separate stylesheet.
    1.27.0 - 2026-08-03 - Slim greeting and the log bar, for today.js
                          2.0.0. Both belong here with the rest of
                          Today rather than in a second stylesheet
                          overriding this one by load order.
    1.26.0 - 2026-07-29 - overflow-x:hidden -> clip. Per spec, a
                          non-visible value on one axis forces the other
                          to auto, so hidden was adding a vertical
                          scrollbar to every task row.
    1.25.0 - 2026-07-29 - One dragon rule, and Today's rows drawn with
                          the Tasks screen's parts.

                          .liq-row-dragon and .liq-task-dragon are
                          deleted. Both existed only because 1.24.0 gave
                          the glyph a new class per screen, when
                          .liq-dragon-mark was already doing the job -
                          which is how the Tasks row ended up rendering
                          two dragons, an svg and an emoji, side by
                          side. One class, one rule.

                          .liq-cell-sig now works inside Today's flex
                          row as well as the Tasks grid, so both screens
                          put the signal diamond in the same place using
                          the same markup. The alternative was a second
                          set of classes that looked the same today and
                          drifted by Friday.

                          .liq-dot is kept: it is a generic marker and
                          other surfaces still use it. It is simply no
                          longer how signal is drawn.
    1.24.0 - 2026-07-29 - Sizing for the dragon glyph in its three
                          homes. Three new prefixes, all scanned first,
                          none existed.

                          IQ.icons.dragon ships at 24x24 because that is
                          the size the CARD wants. Inline in a task row
                          that is far too big, so the row variants
                          constrain the svg to 15px with width/height on
                          the element itself - the icon carries hard
                          width and height attributes, and CSS on the
                          wrapper alone will not shrink it.

                          Colour comes from the wrapper: the glyph is
                          fill="currentColor", so it takes --dragon
                          without a single override inside the svg.

                          .liq-dragon-label and .liq-dragon-mark already
                          existed, so the new properties were MERGED
                          into them rather than added as a second block
                          of the same selector. Two rules for one
                          selector separated by 1800 lines is how a
                          stylesheet becomes impossible to reason about,
                          and the first draft of this change did exactly
                          that.
    1.23.0 - 2026-07-29 - DRAG HANDLE RESTORED on touch widths, and made
                          visible.

                          1.20.0 widened an existing display:none from
                          380px to 600px, which took reordering off
                          every phone. That was never needed - the bug
                          was five children in a six-track template, not
                          the handle costing width. With the handle back
                          the title track still gets 172pt at 320px and
                          242pt at 390px, which is more than it needs.

                          Six children, six tracks, at every width. No
                          display:none anywhere in the row, so the
                          template can never drift out of step with the
                          children again - which is exactly how the
                          title ended up in the 14px signal track.

                          The handle was also effectively invisible:
                          --text-dim at 13px with -3px letter-spacing.
                          Brought up to --text-secondary at 15px with a
                          real 44px hit area, because a control you
                          cannot see is one you do not know you have.
    1.22.0 - 2026-07-29 - .liq-dragon-set, the "make this today's
                          dragon" button in the task editor. New prefix,
                          scanned first, no collision.
                          Dragon-coloured and full width, sitting in the
                          sheet body rather than the foot: the foot is
                          Save / Cancel / Delete and a fourth control
                          there would be cramped on a phone and one slip
                          away from Delete.
                          Outlined rather than filled - Save is the
                          primary action in that sheet and this must not
                          outrank it.
    1.21.0 - 2026-07-29 - Dragon picker styles for today.js 1.6.0, and
                          .liq-dragon-change removed - the three-button
                          panel it styled no longer exists.
                          Rows are full-width taps at 48px, above the
                          44px floor: this is a list you scan and hit
                          once, and the deferral count sits right-
                          aligned so the most-moved task is readable
                          without reading every title.
    1.20.0 - 2026-07-29 - THE TASK ROW, ACTUALLY FIXED.

                          display:none removes a grid child from track
                          assignment ENTIRELY - it does not leave a hole.
                          The narrow-phone rule hid .liq-handle but kept
                          a six-track template with a 0 first track, so
                          the five surviving children each shifted left
                          one track: the checkbox took the 0 track, the
                          signal diamond took 28px, and THE TITLE TOOK
                          THE 14px SIGNAL TRACK - which collapses to
                          min-content and wraps at every word. The
                          importance dots landed in the wide flexible
                          track, which is why they floated out to the
                          right looking like a menu button.

                          1.17.0 widened the title track. The title was
                          never in it. Five children need five tracks.

                          Now applied at every touch width rather than
                          only below 380px, because the handle is a
                          pointer affordance and 20px of invisible
                          --text-dim glyph is not worth the width on any
                          phone.

                          Importance dots dimmed and tightened so they
                          read as a rating rather than as a control.
    1.19.0 - 2026-07-29 - Five new blocks for today.js 1.5.0. Every
                          prefix scanned first and none existed:
                          .liq-quote, .liq-learn, .liq-moment,
                          .liq-dragon-change.

                          NO RED ANYWHERE in these. Not on a missed
                          learning floor, not on the destructive button,
                          not on the moment count. The two moment
                          buttons in particular have to stay cheap to
                          press - one that looks like an alarm gets
                          avoided, and an avoided button produces no
                          data at all. Same argument as the close having
                          no red and the trust bar having no bands.

                          The learning bar is the only progress fill in
                          the product. It fills with --signal when met
                          and --text-dim when not, rather than red -
                          it is a FLOOR, not a verdict, and a bar that
                          goes red every afternoon stops being read by
                          dinner.
    1.18.0 - 2026-07-29 - Check-in submit button had no clearance. Every
                          .liq-check-field carries margin-top:12px, so
                          the fields breathe against each other, but the
                          button after the last one inherited nothing and
                          sat flush against the "what could derail this"
                          input. Two failure modes: it reads as part of
                          the field, and it is a mis-tap away from the
                          text box on a phone.
                          Handled with sibling rules off .liq-check-field
                          and .liq-cscale rather than a class on the
                          button, because the button is a platform .btn
                          and giving every .btn in the app a top margin
                          to fix one screen is how a stylesheet rots.
    1.17.0 - 2026-07-28 - Task rows and the toast.

                          THE TASK ROW. `1fr` in a grid resolves to
                          minmax(AUTO, 1fr), and an auto minimum means
                          min-content. So whenever the two trailing auto
                          tracks wanted more room than the row had, the
                          title track collapsed all the way to the
                          longest single word - which is why "Clean
                          bathrooms" broke across two lines and
                          "2026-07-26" broke at its hyphens (a hyphen is
                          a break opportunity, so min-content of that
                          string is "2026-"). The row then overflowed
                          and pushed the page sideways.
                          Title track is now minmax(120px, 1fr) so it
                          wins the negotiation, and .liq-cell-right can
                          finally shrink instead of forcing the row
                          wide. Meta tokens get white-space:nowrap so a
                          date is never broken mid-string again.

                          THE TOAST. .iq-toast is fixed at bottom:24px,
                          the tab bar is 56px tall and also fixed, so
                          every toast rendered ON TOP of navigation -
                          "Wingman could not respond" sat across Today
                          and Wingman. Lifted using the same calc()
                          .liq-install has used since it shipped. A
                          platform class overridden from the product
                          file on purpose: the product's tab bar is what
                          creates the collision, so the product owns the
                          fix. Precedent already here in .iq-login-wrap
                          and .iq-content > *.
    1.16.0 - 2026-07-28 - .liq-read-row had no gap. space-between is
                         enough for "Sleep / 7h 30m", but Intent and Risk
                         hold sentences: the value fills the row, there is
                         no space left to distribute, and the label ends up
                         welded to the first word - "IntentI overslept".
                         Adds a gap, stops the label shrinking, and lets
                         the value take the remaining width. min-width:0 on
                         the value because a flex item defaults to
                         min-width:auto and will not wrap below its longest
                         word without it.
    1.15.0 - 2026-07-27 - .liq-qa-go becomes a labelled Add button and
                         .liq-qa-new is removed - the bar had two
                         unlabelled icon buttons doing different things.
                         Rule followed: edited in place, not duplicated.
    1.14.0 - 2026-07-27 - Goals screen. Twenty new .liq-goal- selectors,
                         all scanned against this file first; none
                         existed. Status modifiers reuse the signal
                         palette rather than minting new colours - a hit
                         goal is signal green, a missed one is noise red,
                         which is the same vocabulary every other screen
                         already speaks.
    1.13.0 - 2026-07-27 - Login card centres again. shell.css gives
                         .iq-login-wrap display:flex with align-items:center
                         but only max-height:100%, and a flex container with
                         no height collapses to its content - so there was
                         nothing to centre within and the card sat at the
                         top. The platform gets away with it because its
                         login wrapper is a CHILD of ##iq-root and inherits
                         the grid's height; in Life IQ index.cfm makes it a
                         SIBLING, which also means shell.css's
                         ##iq-root:has(.iq-login-wrap) rule never matches
                         anything here. Renewal IQ solves it by giving
                         .riq-login-wrap height:100vh outright; same fix,
                         overridden on the product side because the DOM
                         difference is Life IQ's, not the platform's.
    1.12.0 - 2026-07-26 - .is-missing flash for a required field the user
                         skipped. Paired with a scrollIntoView in tasks.js
                         because a highlight below the fold is the same as
                         no highlight, which is how a refused save came to
                         look like a dead Save button.
    1.11.0 - 2026-07-25 - Task editor rebuilt as a bottom sheet.
                         .liq-modal-wrap/.liq-modal replaced in place by
                         .liq-sheet-wrap/.liq-sheet rather than added
                         beside them - nothing else used the old pair.
                         Sheet pins head and foot and scrolls only the
                         field body, because a keyboard on a phone leaves
                         roughly 40% of the viewport and Save has to live
                         in it. Desktop keeps a centered panel through
                         one pointer:fine query. .liq-modal-title and
                         .liq-modal .form-label kept - the markup still
                         uses both.
    1.10.0 - 2026-07-25 - .liq-req added for the "pick one" hint beside the
                         Priority label in the task editor, now that priority
                         has no default. Uses --yellow: the field is
                         incomplete, not in error, and --red reads as a
                         failure the user has not made yet.
    1.9.0 - 2026-07-25 - Settings category editor styles: row grid, colour
                         input, Google-colour select, delete, and the narrow
                         phone stack.
    1.8.0 - 2026-07-25 - Tasks screen rebuilt to Tasks IQ parity. .liq-task
                         converted from flex to a five-track grid and
                         .liq-check from a rounded square to a circle (both
                         edited in place). Added quick-add bar, scope tabs,
                         signal count strip, signal diamond, row meta line,
                         drag handle, importance dots, subtask panel, and the
                         full editor.
    1.7.0 - 2026-07-23 - Identity and Memory view styles.
    1.6.0 - 2026-07-23 - Install bar styles for add-to-home-screen.
    1.5.0 - 2026-07-23 - Check-in styles: the 1-5 scale buttons, the
                         evening mirror, and the read-back rows.
    1.4.0 - 2026-07-23 - Task list styles: rows, checkbox, defer
                         button, and the deferral warning.
    1.3.0 - 2026-07-23 - Reality log styles: entry rows, the log form,
                         and the review queue with its one-tap
                         classify buttons.
    1.2.0 - 2026-07-22 - Wingman proposal styles and settings styles
                         added.
    1.1.0 - 2026-07-22 - Fourth signal state added. .liq-dot-unclassified
                         is a hollow ring rather than a fourth solid
                         color so an unresolved item reads as visually
                         incomplete, and .liq-seg-unclassified is a
                         diagonal hatch so unclassified time in the
                         reality bar looks deliberately uncounted rather
                         than like a rendering gap.
    1.0.0 - 2026-07-22 - Initial version.
================================================================================
*/


/* ============================================================================
   Shared primitives
   ============================================================================ */

.liq-card {
  background: var(--bg-surface, #16161a);
  border: 1px solid var(--border-light, rgba(255,255,255,0.07));
  border-radius: var(--radius-lg, 14px);
  padding: 14px 16px;
  margin-bottom: 14px;
}

.liq-section-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  margin: 22px 2px 8px;
}

.liq-section-label {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.10em;
  text-transform: uppercase;
  color: var(--text-dim);
}

.liq-section-count {
  font-size: 12px;
  color: var(--text-secondary);
}

.liq-empty-soft {
  color: var(--text-dim);
  font-size: 14px;
  line-height: 1.55;
  text-align: center;
  padding: 20px 16px;
}


/* ============================================================================
   Greeting
   ============================================================================ */

.liq-greeting {
  margin: 4px 2px 16px;
}

.liq-date {
  font-size: 12px;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--text-dim);
}

.liq-hello {
  font-size: 22px;
  font-weight: 600;
  color: var(--text-primary);
  margin-top: 3px;
  line-height: 1.2;
}

/* Slim variant. Name and date on one row.

   The stacked version above owned the top of the screen and pushed the
   task list below the fold on a phone, to say something the user
   already knew. Today opens on the work now, and this gets one line. */

.liq-greeting--slim {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  min-width: 0;
  margin: 0 2px 12px;
}

.liq-greeting--slim .liq-hello {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 16px;
  line-height: 1.3;
  margin-top: 0;
}

.liq-greeting--slim .liq-date {
  flex: 0 0 auto;
  line-height: 1.3;
}

/* ============================================================================
   Log bar - sits under the task list on Today
   ============================================================================ */

/* Time logging is a daily action and used to be reachable only by
   switching tabs, which is most of why a day went by unlogged. */

.liq-logbar {
  display: flex;
  gap: 8px;
  margin: 8px 0 20px;
  min-width: 0;
}

.liq-logbar-btn {
  flex: 1 1 0;
  min-width: 0;
  min-height: var(--touch-target-touch, 44px);
  padding: 0 12px;
  background: var(--accent-dim);
  border: 1px solid var(--accent-bord);
  border-radius: 8px;
  color: var(--accent-light);
  font-family: inherit;
  font-size: 14px;
  cursor: pointer;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.liq-logbar-btn:active {
  background: var(--accent);
  color: var(--bg-base);
}

/* Reviewing the log is not the daily action; writing to it is. Same
   size for the thumb, less weight for the eye. */
.liq-logbar-btn.is-quiet {
  flex: 0 1 auto;
  background: transparent;
  border-color: var(--border);
  color: var(--text-secondary);
}

.liq-morning-read {
  background: var(--accent-dim);
  border-left: 3px solid var(--accent);
  border-radius: var(--radius, 8px);
  padding: 12px 14px;
  margin-bottom: 16px;
  font-size: 14px;
  line-height: 1.6;
  color: var(--text-primary);
}


/* ============================================================================
   Open / close the day

   These are full-width and unmissable on purpose. The morning open and
   the evening close are the two moments the whole product depends on,
   and a subtle link would lose to everything else on the screen.
   ============================================================================ */

.liq-open-day,
.liq-close-day {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 3px;
  width: 100%;
  min-height: 60px;
  padding: 13px 16px;
  margin-bottom: 16px;
  background: var(--accent-dim);
  border: 1px solid var(--accent-bord);
  border-radius: var(--radius-lg, 14px);
  color: var(--text-primary);
  text-align: left;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

.liq-close-day {
  margin-top: 8px;
}

.liq-open-day-label,
.liq-close-day-label {
  font-size: 16px;
  font-weight: 600;
}

.liq-open-day-sub,
.liq-close-day-sub {
  font-size: 13px;
  color: var(--text-secondary);
}

.liq-closed {
  text-align: center;
  font-size: 13px;
  color: var(--text-dim);
  padding: 18px 0 6px;
}


/* ============================================================================
   Quote line (today.js 1.5.0)
   Sits under the greeting. Server keeps it sticky for an hour so it
   cannot change mid-read.
   ============================================================================ */

.liq-quote {
  display: flex;
  flex-direction: column;
  gap: 4px;
  margin: 0 0 16px;
  padding: 12px 14px;
  background: var(--bg-surface);
  border-left: 2px solid var(--accent-bord);
  border-radius: var(--radius, 8px);
  min-width: 0;
}

.liq-quote-text {
  font-size: 15px;
  line-height: 1.45;
  color: var(--text-secondary);
  overflow-wrap: anywhere;
}

.liq-quote-src {
  font-size: var(--font-min-display);
  color: var(--text-dim);
}


/* ============================================================================
   The dragon glyph (today.js 1.7.0, tasks.js 2.10.0)

   fill="currentColor" in the icon, so colour is set here on the wrapper
   and nothing inside the svg is ever overridden.

   The icon carries width="24" height="24" attributes. Those win over a
   wrapper's font-size, so the row variants set width/height on the svg
   element directly - anything less and it renders at full 24 in a 44px
   row.
   ============================================================================ */

/* ============================================================================
   Task editor: make this today's dragon (tasks.js 2.9.0)
   Outlined, not filled. Save is the primary action in that sheet and
   this one must not outrank it.
   ============================================================================ */

.liq-dragon-set {
  display: block;
  width: 100%;
  min-height: var(--touch-target-touch, 44px);
  margin-top: 18px;
  padding: 0 14px;
  background: transparent;
  border: 1px solid var(--dragon-bord, var(--border));
  border-radius: var(--radius, 8px);
  color: var(--dragon, var(--text-primary));
  font-family: var(--font-ui);
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

.liq-dragon-set:hover {
  background: var(--dragon-dim, var(--bg-raised));
}


/* ============================================================================
   Dragon picker (today.js 1.6.0)
   Open tasks, listed on the card itself. Choosing the dragon used to
   navigate to the Tasks screen, which is leaving rather than choosing -
   nothing over there knew why you had arrived.
   ============================================================================ */

.liq-dragon-pick {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-top: 10px;
  min-width: 0;
}

.liq-dragon-pick-note {
  padding: 10px 2px;
  font-size: var(--font-min-secondary);
  color: var(--text-dim);
}

.liq-dragon-pick-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  width: 100%;
  min-height: 48px;
  padding: 8px 12px;
  background: var(--bg-base);
  border: 1px solid var(--border);
  border-radius: var(--radius, 8px);
  color: var(--text-primary);
  font-family: var(--font-ui);
  font-size: 15px;
  text-align: left;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  min-width: 0;
}

.liq-dragon-pick-item:hover {
  border-color: var(--dragon-bord, var(--accent-bord));
}

.liq-dragon-pick-title {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* The thing you keep moving is usually the dragon, so the count earns
   its place - but it stays dim. It is evidence, not an accusation. */
.liq-dragon-pick-defer {
  flex: 0 0 auto;
  font-size: var(--font-min-display);
  color: var(--text-dim);
}

.liq-dragon-pick-foot {
  display: flex;
  gap: 6px;
  margin-top: 4px;
}

.liq-dragon-pick-foot .btn-sm {
  flex: 1 1 0;
  min-width: 0;
  min-height: var(--touch-target-min, 40px);
}


/* ============================================================================
   Learning floor (today.js 1.5.0)
   Minutes against the target. The only progress bar in the product.
   Fills with --signal when met and --text-dim when not. NEVER red: this
   is a floor, not a verdict, and a bar that goes red every afternoon
   stops being read by dinner.
   ============================================================================ */

.liq-learn {
  margin: 0 0 16px;
  padding: 12px 14px;
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius, 8px);
  min-width: 0;
}

.liq-learn-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 8px;
  min-width: 0;
}

.liq-learn-label {
  font-size: 13px;
  color: var(--text-secondary);
}

.liq-learn-num {
  font-size: 13px;
  color: var(--text-dim);
  white-space: nowrap;
}

.liq-learn.is-met .liq-learn-num {
  color: var(--signal);
}

.liq-learn-track {
  height: 4px;
  background: var(--bg-raised);
  border-radius: 999px;
  overflow: hidden;
}

.liq-learn-fill {
  height: 100%;
  background: var(--text-dim);
  border-radius: 999px;
  transition: width var(--t-medium, 200ms) ease;
}

.liq-learn.is-met .liq-learn-fill {
  background: var(--signal);
}


/* ============================================================================
   The two moment buttons (today.js 1.5.0)
   "Rough one" sets the day's tone. "I am doing it" is the interrupt.

   NEITHER IS STYLED AS AN ALARM. No red, no warning border, nothing
   that makes pressing it feel like an admission with a cost. A button
   that looks expensive gets avoided, and an avoided button produces no
   data - which is worse than not having it. Trust never reads this
   table either.
   ============================================================================ */

.liq-moment-bar {
  display: flex;
  gap: 8px;
  margin: 0 0 16px;
  min-width: 0;
}

.liq-moment-btn {
  flex: 1 1 0;
  min-width: 0;
  min-height: var(--touch-target-touch, 44px);
  padding: 0 10px;
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius, 8px);
  color: var(--text-dim);
  font-family: var(--font-ui);
  font-size: 13px;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.liq-moment-btn:hover {
  color: var(--text-secondary);
  border-color: var(--border-light, var(--border));
}

/* Tapped today. Acknowledged, not flagged. */
.liq-moment-btn.is-on {
  background: var(--bg-raised);
  color: var(--text-secondary);
}

/* The interrupt gets the dragon colour, not red. It is the same kind of
   thing as the dragon - a hard moment, named on purpose. */
.liq-moment-btn--stop {
  border-color: var(--dragon-bord, var(--border));
  color: var(--text-secondary);
}

.liq-moment-n {
  display: inline-block;
  margin-left: 4px;
  color: var(--text-dim);
}


/* ============================================================================
   Dragon

   Warm border and its own palette so the card reads as different in
   kind from everything else on the screen, not merely more important.
   ============================================================================ */

.liq-dragon {
  border: 2px solid var(--dragon-bord);
  background: var(--dragon-dim);
}

.liq-dragon-label {
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.14em;
  color: var(--dragon);
  margin-bottom: 7px;
}

.liq-dragon-title {
  font-size: 17px;
  font-weight: 600;
  line-height: 1.32;
  color: var(--text-primary);
}

.liq-dragon-why {
  font-size: 14px;
  line-height: 1.55;
  color: var(--text-secondary);
  margin-top: 6px;
}

.liq-dragon-none {
  font-size: 15px;
  color: var(--text-dim);
  padding: 4px 0 2px;
}

.liq-dragon-meta {
  display: flex;
  gap: 14px;
  margin-top: 9px;
  font-size: 12px;
  color: var(--text-dim);
}

.liq-dragon-actions {
  display: flex;
  gap: 8px;
  margin-top: 13px;
}

.liq-dragon-actions .btn {
  flex: 1;
  min-height: 44px;
}

.liq-dragon-actions .btn + .btn {
  flex: 0 0 88px;
}

.liq-dragon-done {
  opacity: 0.75;
}

.liq-dragon-outcome {
  margin-top: 12px;
  padding: 8px 12px;
  border-radius: var(--radius, 8px);
  font-size: 13px;
  font-weight: 600;
  text-align: center;
}

.liq-outcome-slayed       { background: var(--signal-dim);    color: var(--signal); }
.liq-outcome-partial      { background: var(--necessary-dim); color: var(--text-secondary); }
.liq-outcome-untouched    { background: var(--noise-dim);     color: var(--noise); }
.liq-outcome-wrong_dragon { background: var(--necessary-dim); color: var(--text-secondary); }


/* ============================================================================
   Lists and rows
   ============================================================================ */

.liq-list {
  padding: 0;
  overflow: hidden;
}

.liq-row {
  display: flex;
  align-items: flex-start;
  gap: 11px;
  width: 100%;
  padding: 12px 14px;
  border-bottom: 1px solid var(--border-light, rgba(255,255,255,0.06));
  background: transparent;
  text-align: left;
}

.liq-row:last-child {
  border-bottom: 0;
}

.liq-row-body {
  flex: 1;
  min-width: 0;
}

.liq-row-title {
  font-size: 15px;
  line-height: 1.35;
  color: var(--text-primary);
  word-break: break-word;
}

.liq-row-sub {
  font-size: 12px;
  color: var(--text-dim);
  margin-top: 3px;
}

.liq-row-done .liq-row-title {
  color: var(--text-dim);
  text-decoration: line-through;
}

.liq-row-more {
  justify-content: center;
  color: var(--accent);
  font-size: 14px;
  min-height: 46px;
  border: 0;
  cursor: pointer;
}

.liq-deferred {
  color: var(--dragon);
}


/* Checkbox. 28px visual, 44px hit area via padding on the row. */
.liq-check {
  flex: 0 0 auto;
  width: 26px;
  height: 26px;
  margin-top: 1px;
  border: 2px solid var(--border, rgba(255,255,255,0.18));
  border-radius: 999px;
  background: transparent;
  color: var(--bg-base);
  font-size: 15px;
  line-height: 1;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

.liq-row-done .liq-check {
  background: var(--signal);
  border-color: var(--signal);
}


/* ============================================================================
   Signal dots and bar

   The only palette in the app meant to be read as meaning rather than
   decoration. Green moves life forward, grey must be done, red does not
   earn its time.
   ============================================================================ */

.liq-dot {
  flex: 0 0 auto;
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  margin-top: 7px;
}

.liq-legend .liq-dot {
  margin: 0 5px 0 0;
  vertical-align: middle;
}

.liq-dot-signal    { background: var(--signal); }
.liq-dot-necessary { background: var(--necessary); }
.liq-dot-noise     { background: var(--noise); }

/*
  Unclassified is a hollow ring, not a fourth solid color. It has to
  read as visually incomplete - a screen with unclassified items should
  look unfinished, and that is the nudge to go resolve them. box-sizing
  keeps the ring the same 8px outer diameter as the filled dots so the
  row alignment does not shift.
*/
.liq-dot-unclassified {
  background: var(--unclassified);
  border: 1.5px solid var(--unclassified-ring);
  box-sizing: border-box;
}

.liq-pvr {
  display: flex;
  justify-content: space-between;
  font-size: 13px;
  color: var(--text-secondary);
  margin-bottom: 10px;
}

.liq-bar {
  display: flex;
  height: 10px;
  border-radius: 5px;
  overflow: hidden;
  background: var(--bg-elevated, #1e1e24);
}

.liq-bar-seg {
  display: block;
  height: 100%;
}

.liq-seg-signal    { background: var(--signal); }
.liq-seg-necessary { background: var(--necessary); }
.liq-seg-noise     { background: var(--noise); }

/*
  A transparent segment in the bar would look like a rendering bug, so
  unclassified time reads as a faint diagonal hatch instead: clearly
  present, clearly not yet counted as anything. The bar only sums to
  100% once this segment is gone.
*/
.liq-seg-unclassified {
  background-color: var(--unclassified-dim);
  background-image: repeating-linear-gradient(
    45deg,
    transparent,
    transparent 3px,
    var(--unclassified-bord) 3px,
    var(--unclassified-bord) 5px
  );
}

.liq-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
  margin-top: 10px;
  font-size: 12px;
  color: var(--text-secondary);
}


/* ============================================================================
   Timer - the running reality-log entry
   ============================================================================ */

.liq-timer {
  display: flex;
  align-items: center;
  gap: 12px;
  border: 1px solid var(--signal-bord);
  background: var(--signal-dim);
}

.liq-timer-pulse {
  flex: 0 0 auto;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--signal);
  animation: liq-pulse 2s ease-in-out infinite;
}

@keyframes liq-pulse {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.35; }
}

.liq-timer-body { flex: 1; min-width: 0; }

.liq-timer-title {
  font-size: 15px;
  font-weight: 600;
  color: var(--text-primary);
}

.liq-timer-elapsed {
  font-family: var(--font-mono, 'JetBrains Mono', monospace);
  font-size: 13px;
  color: var(--text-secondary);
  margin-top: 2px;
}

.liq-timer-stop {
  flex: 0 0 auto;
  min-width: 72px;
  min-height: 44px;
}

@media (prefers-reduced-motion: reduce) {
  .liq-timer-pulse { animation: none; }
}


/* ============================================================================
   Chips - onboarding and anywhere a set of choices beats a text field

   The whole reason onboarding uses chips: someone who cannot yet
   articulate what is wrong can still recognize it in a list.
   ============================================================================ */

.liq-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: 4px 0 16px;
}

.liq-chip {
  min-height: 44px;
  padding: 10px 15px;
  border: 1px solid var(--border, rgba(255,255,255,0.16));
  border-radius: 22px;
  background: transparent;
  color: var(--text-secondary);
  font-size: 14px;
  line-height: 1.2;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: background var(--t-fast, 120ms) ease,
              border-color var(--t-fast, 120ms) ease,
              color var(--t-fast, 120ms) ease;
}

.liq-chip.selected {
  background: var(--accent-dim);
  border-color: var(--accent);
  color: var(--text-primary);
}

.liq-q-title {
  font-size: 20px;
  font-weight: 600;
  line-height: 1.3;
  color: var(--text-primary);
  margin-bottom: 4px;
}

.liq-q-sub {
  font-size: 14px;
  color: var(--text-secondary);
  margin-bottom: 16px;
  line-height: 1.5;
}

.liq-q-progress {
  font-size: 12px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-dim);
  margin-bottom: 10px;
}

.liq-q-nav {
  display: flex;
  gap: 10px;
  margin-top: 20px;
}

.liq-q-nav .btn {
  flex: 1;
  min-height: 48px;
}


/* ============================================================================
   Chat
   ============================================================================ */

.liq-chat {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding-bottom: 8px;
}

.liq-msg {
  max-width: 86%;
  padding: 11px 14px;
  border-radius: 16px;
  font-size: 15px;
  line-height: 1.55;
  word-break: break-word;
  white-space: pre-wrap;
}

.liq-msg-user {
  align-self: flex-end;
  background: var(--accent);
  color: #ffffff;
  border-bottom-right-radius: 5px;
}

.liq-msg-assistant {
  align-self: flex-start;
  background: var(--bg-surface, #16161a);
  border: 1px solid var(--border-light, rgba(255,255,255,0.07));
  color: var(--text-primary);
  border-bottom-left-radius: 5px;
}

.liq-msg-pending {
  opacity: 0.55;
}

.liq-composer {
  position: sticky;
  bottom: 0;

  /* Column, not row. The textarea used to share a row with two buttons,
     which left it about a thumb wide and one line tall - tapping into it
     missed more often than it hit. It gets the full width now and the
     buttons go underneath. */
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 10px 0;
  background: var(--bg-base);
}

.liq-composer-in {
  width: 100%;
  min-height: 84px;
  max-height: 200px;
  padding: 12px;
  background: var(--bg-raised);
  border: 1px solid var(--border-light, var(--border));
  border-radius: 10px;
  color: var(--text-primary);
  font-family: inherit;

  /* 16px minimum or iOS zooms the page on focus. */
  font-size: 16px;
  line-height: 1.45;
  resize: none;
  overflow-y: auto;
}

.liq-composer-in:focus {
  outline: none;
  border-color: var(--accent);
}

/* Send is the common act and gets the width. Make tasks is occasional
   and reads as secondary, which is what it is. */
.liq-composer-btns {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 8px;
}

.liq-composer-btn {
  min-height: var(--touch-target-touch, 44px);
  padding: 0 16px;
  background: transparent;
  border: 1px solid var(--border-light, var(--border));
  border-radius: 9px;
  color: var(--text-secondary);
  font-family: inherit;
  font-size: 14.5px;
  white-space: nowrap;
  cursor: pointer;
}

.liq-composer-btn.is-primary {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--bg-base);
  font-weight: 600;
}




/* ============================================================================
   Scales - energy, stress, mood, day score
   ============================================================================ */

.liq-scale {
  margin-bottom: 18px;
}

.liq-scale-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  margin-bottom: 8px;
}

.liq-scale-label {
  font-size: 15px;
  color: var(--text-primary);
}

.liq-scale-value {
  font-family: var(--font-mono, 'JetBrains Mono', monospace);
  font-size: 18px;
  font-weight: 600;
  color: var(--accent);
}

.liq-scale input[type="range"] {
  width: 100%;
  height: 44px;
}


/* ============================================================================
   Memory management

   Standing and transient are visually distinct because the difference
   is the whole model: one can never be finished, the other expires.
   ============================================================================ */

.liq-mem {
  display: flex;
  align-items: flex-start;
  gap: 11px;
  padding: 12px 14px;
  border-bottom: 1px solid var(--border-light, rgba(255,255,255,0.06));
}

.liq-mem:last-child { border-bottom: 0; }

.liq-mem-body { flex: 1; min-width: 0; }

.liq-mem-text {
  font-size: 15px;
  line-height: 1.45;
  color: var(--text-primary);
  word-break: break-word;
}

.liq-mem-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 5px;
  font-size: 11px;
  color: var(--text-dim);
}

.liq-mem-type {
  display: inline-block;
  padding: 2px 8px;
  border-radius: 10px;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.liq-mem-standing  { background: var(--accent-dim);    color: var(--accent-light); }
.liq-mem-transient { background: var(--necessary-dim); color: var(--text-secondary); }

.liq-mem-actions {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.liq-mem-btn {
  min-width: 44px;
  min-height: 36px;
  padding: 0 10px;
  background: transparent;
  border: 1px solid var(--border-light, rgba(255,255,255,0.10));
  border-radius: var(--radius-sm, 6px);
  color: var(--text-dim);
  font-size: 12px;
  cursor: pointer;
}

.liq-mem-btn-danger { color: var(--noise); }

.liq-mem-archived { opacity: 0.55; }

.liq-tabs-inline {
  display: flex;
  gap: 6px;
  margin-bottom: 14px;
}

.liq-tab-inline {
  flex: 1;
  min-height: 40px;
  padding: 9px 10px;
  border: 1px solid var(--border-light, rgba(255,255,255,0.10));
  border-radius: var(--radius, 8px);
  background: transparent;
  color: var(--text-secondary);
  font-size: 13px;
  cursor: pointer;
}

.liq-tab-inline.active {
  background: var(--accent-dim);
  border-color: var(--accent-bord);
  color: var(--text-primary);
}


/* ============================================================================
   Identity sections
   ============================================================================ */

.liq-ident-section {
  padding: 12px 14px;
  border-bottom: 1px solid var(--border-light, rgba(255,255,255,0.06));
}

.liq-ident-section:last-child { border-bottom: 0; }

.liq-ident-label {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-dim);
  margin-bottom: 4px;
}

.liq-ident-content {
  font-size: 15px;
  line-height: 1.55;
  color: var(--text-primary);
}

.liq-ident-off { opacity: 0.45; }


/* ============================================================================
   Reality log rows
   ============================================================================ */

.liq-log-time {
  flex: 0 0 52px;
  font-family: var(--font-mono, 'JetBrains Mono', monospace);
  font-size: 12px;
  color: var(--text-dim);
  padding-top: 2px;
}

.liq-log-dur {
  flex: 0 0 auto;
  font-family: var(--font-mono, 'JetBrains Mono', monospace);
  font-size: 13px;
  color: var(--text-secondary);
  padding-top: 1px;
}


/* ============================================================================
   Question card - the single evening question
   ============================================================================ */

.liq-question {
  font-family: var(--font-display, 'Barlow Condensed', sans-serif);
  font-size: 21px;
  font-weight: 500;
  line-height: 1.35;
  color: var(--text-primary);
  margin-bottom: 12px;
}

.liq-answer {
  width: 100%;
  min-height: 110px;
  resize: vertical;
  font-size: 15px;
  line-height: 1.5;
}


/* ============================================================================
   Outcome picker - the four dragon answers
   ============================================================================ */

.liq-outcomes {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
  margin-top: 10px;
}

.liq-outcome-btn {
  min-height: 52px;
  padding: 10px 12px;
  border: 1px solid var(--border, rgba(255,255,255,0.16));
  border-radius: var(--radius, 8px);
  background: transparent;
  color: var(--text-secondary);
  font-size: 14px;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

.liq-outcome-btn.selected {
  background: var(--accent-dim);
  border-color: var(--accent);
  color: var(--text-primary);
}


/* ============================================================================
   Desktop: constrain line length. The app is mobile-first but a laptop
   should not stretch a task title across 1400px.
   ============================================================================ */

@media (pointer: fine) {

  .iq-content > * {
    max-width: 720px;
  }

}

/* ============================================================================
   Settings
   Every control saves on touch, so there is no form, no submit button,
   and no unsaved state. Rows are full-width tap targets.
   ============================================================================ */

.liq-settings {
  padding-bottom: 24px;
}

.liq-opt-list {
  padding: 0;
  overflow: hidden;
}

.liq-opt {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  min-height: var(--touch-target-touch, 44px);
  padding: 12px 16px;
  background: none;
  border: 0;
  border-bottom: 1px solid var(--border);
  text-align: left;
  color: var(--text-primary);
  font-family: var(--font-ui);
  cursor: pointer;
}

.liq-opt:last-child {
  border-bottom: 0;
}

.liq-opt.active {
  background: var(--accent-dim);
}

.liq-opt-body {
  flex: 1 1 auto;
  min-width: 0;
}

.liq-opt-label {
  display: block;
  font-size: 15px;
  font-weight: 600;
}

.liq-opt-note {
  display: block;
  margin-top: 2px;
  font-size: 13px;
  color: var(--text-secondary);
}

.liq-opt-caption {
  font-size: 13px;
  color: var(--text-secondary);
  margin-bottom: 10px;
}

.liq-opt-check {
  flex: 0 0 auto;
  width: 18px;
  font-size: 15px;
  color: var(--accent);
  text-align: center;
}

.liq-opt-chev {
  flex: 0 0 auto;
  font-size: 22px;
  line-height: 1;
  color: var(--text-dim);
}

/*
  Swatches preview the signal quad, not the brand color - the quad is
  the only palette that carries meaning. Each swatch row paints from its
  own theme block so a row shows that theme's colors without the theme
  being applied.
*/
.liq-swatches {
  flex: 0 0 auto;
  display: inline-flex;
  gap: 5px;
  align-items: center;
}

.liq-swatches .liq-dot {
  margin-top: 0;
  width: 10px;
  height: 10px;
}

.liq-seg-row {
  display: flex;
  gap: 6px;
}

.liq-seg-btn {
  flex: 1 1 0;
  min-height: var(--touch-target-touch, 44px);
  padding: 8px 4px;
  background: var(--bg-raised);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  color: var(--text-secondary);
  font-family: var(--font-ui);
  font-weight: 600;
  cursor: pointer;
}

.liq-seg-btn.active {
  background: var(--accent-dim);
  border-color: var(--accent-bord);
  color: var(--accent);
}

/* Each step renders at its own scale so the choice is legible before
   it is committed to. */
.liq-seg-small  { font-size: 12px; }
.liq-seg-medium { font-size: 14px; }
.liq-seg-large  { font-size: 16px; }
.liq-seg-xlarge { font-size: 18px; }

.liq-acct-email {
  font-size: 14px;
  color: var(--text-secondary);
  margin-bottom: 12px;
  word-break: break-all;
}

.liq-signout {
  color: var(--red-text);
  border-color: var(--red-bord);
}


/* ============================================================================
   Wingman proposals
   The review pass between what the model suggested and what gets written.
   Every field is editable in place because correcting a bad estimate has
   to be possible without going back to the model.
   ============================================================================ */

.liq-prop-wrap {
  margin: 14px 0;
  padding: 12px;
  background: var(--bg-raised);
  border: 1px solid var(--accent-bord);
  border-radius: var(--radius-lg, 14px);
}

.liq-prop-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 10px;
}

.liq-prop-total {
  font-size: 13px;
  color: var(--text-secondary);
  font-variant-numeric: tabular-nums;
}

.liq-prop {
  padding: 10px;
  margin-bottom: 8px;
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
}

.liq-prop-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 6px;
}

.liq-prop-kind {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.06em;
  color: var(--text-dim);
}

.liq-prop-kind-dragon {
  color: var(--dragon);
}

.liq-prop-del {
  min-width: var(--touch-target-min, 40px);
  min-height: var(--touch-target-min, 40px);
  background: none;
  border: 0;
  color: var(--text-dim);
  font-size: 20px;
  line-height: 1;
  cursor: pointer;
}

.liq-prop-title {
  width: 100%;
  margin-bottom: 8px;
}

.liq-prop-fields {
  display: flex;
  gap: 8px;
}

.liq-prop-field {
  flex: 1 1 0;
  min-width: 0;
}

.liq-prop-field span {
  display: block;
  font-size: 12px;
  color: var(--text-dim);
  margin-bottom: 3px;
}

.liq-prop-field .form-input {
  width: 100%;
}

.liq-prop-why {
  margin-top: 6px;
  font-size: 12px;
  color: var(--text-dim);
  font-style: italic;
}

.liq-prop-actions {
  display: flex;
  gap: 8px;
  margin-top: 4px;
}

.liq-prop-actions .btn {
  flex: 1 1 0;
}




/* ============================================================================
   Reality log
   The day's entries, the add form, and the review queue. Queue rows get
   their own one-tap classify buttons because clearing the queue has to
   cost one tap per item, not a trip through the edit form.
   ============================================================================ */

.liq-day-nav {
  display: flex;
  gap: 4px;
}

.liq-entries {
  padding: 0;
  overflow: hidden;
}

.liq-entry {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  width: 100%;
  min-height: var(--touch-target-touch, 44px);
  padding: 11px 14px;
  border-bottom: 1px solid var(--border);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

.liq-entry:last-child {
  border-bottom: 0;
}

.liq-entry-body {
  flex: 1 1 auto;
  min-width: 0;
}


.liq-entry-desc {
  display: block;
  font-size: 15px;
  color: var(--text-primary);
}

.liq-entry-meta {
  display: block;
  margin-top: 2px;
  font-size: 12px;
  color: var(--text-dim);
  font-variant-numeric: tabular-nums;
}

.liq-logform-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 10px;
}

.liq-logform .form-input {
  width: 100%;
}

.liq-logform-row {
  display: flex;
  gap: 8px;
  margin-top: 10px;
}

.liq-logform-row .liq-prop-field {
  flex: 1 1 0;
  min-width: 0;
}

.liq-logform .btn-block {
  width: 100%;
  margin-top: 14px;
}

.liq-queue-count {
  font-size: 12px;
  color: var(--text-dim);
  font-variant-numeric: tabular-nums;
}

.liq-queue-note {
  font-size: 13px;
  color: var(--text-secondary);
  line-height: 1.5;
  margin-bottom: 10px;
}

.liq-qrow {
  margin-bottom: 8px;
}

.liq-qrow-desc {
  font-size: 15px;
  color: var(--text-primary);
  margin-bottom: 2px;
}

.liq-qrow-meta {
  font-size: 12px;
  color: var(--text-dim);
  margin-bottom: 10px;
  font-variant-numeric: tabular-nums;
}

.liq-qrow-btns {
  display: flex;
  gap: 6px;
}

.liq-qbtn {
  flex: 1 1 0;
  min-height: var(--touch-target-touch, 44px);
  padding: 8px 4px;
  background: var(--bg-raised);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  color: var(--text-secondary);
  font-family: var(--font-ui);
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

.liq-qbtn-signal    { color: var(--signal);    border-color: var(--signal-bord); }
.liq-qbtn-necessary { color: var(--necessary); border-color: var(--necessary-bord); }
.liq-qbtn-noise     { color: var(--noise);     border-color: var(--noise-bord); }


/* ============================================================================
   Task list
   ============================================================================ */

.liq-scope-row {
  margin-bottom: 14px;
}

/* Six fixed tracks:
   handle | check | signal | title+meta | marks | chevron.
   Fixed rather than auto so every row aligns whether or not the
   optional parts are present. The right cell holds the dragon
   glyph OR the importance dots, never both, so its width is
   constant. Worth and cost share ONE track now - they were two, with
   the title stretching between them, which put them a thumb apart on a
   long title and made them read as two unrelated facts. Both marks are
   fixed width, so the track is stable at auto. */
.liq-task {
  display: grid;
  /* minmax(120px, 1fr), NOT 1fr. A bare 1fr is minmax(auto, 1fr) and
     that auto minimum is min-content - so the title track was legally
     allowed to collapse to the longest word whenever the trailing auto
     tracks asked for room. A floor here makes the title win instead. */
  grid-template-columns: 20px 30px 16px minmax(120px, 1fr) auto auto;
  align-items: center;
  gap: 10px;
  padding: 11px 14px;
  border-bottom: 1px solid var(--border);
  touch-action: pan-y;
  max-width: 100%;
}

.liq-task.done .liq-task-title {
  color: var(--text-dim);
  text-decoration: line-through;
}

.liq-task.dragging {
  opacity: 0.55;
  background: var(--bg-raised);
}

.liq-task:last-child {
  border-bottom: 0;
}

.liq-task.is-done .liq-task-title {
  color: var(--text-dim);
  text-decoration: line-through;
}

/* Matches the .liq-row-done convention the Today screen already uses -
   the parent state drives the check, not a class on the button. */
.liq-task.done .liq-check,
.liq-task.is-done .liq-check {
  background: var(--signal);
  border-color: var(--signal);
}

.liq-task-body {
  flex: 1 1 auto;
  min-width: 0;
  cursor: pointer;
}

.liq-task-title {
  display: block;
  font-size: 15px;
  color: var(--text-primary);
}

.liq-task-title .liq-dot {
  margin: 0 7px 0 0;
  vertical-align: middle;
}

.liq-defer-btn {
  flex: 0 0 auto;
  min-width: var(--touch-target-min, 40px);
  min-height: var(--touch-target-min, 40px);
  background: none;
  border: 0;
  color: var(--text-dim);
  font-size: 17px;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

.liq-defer-warn {
  color: var(--dragon);
}

.liq-danger-btn {
  width: 100%;
  margin-top: 8px;
  color: var(--noise);
  border-color: var(--noise-bord);
}


/* ============================================================================
   Check-in
   Five inputs in the morning, a mirror and one question at night.
   Scales are buttons rather than sliders - on a phone a slider is a
   fight and five buttons is one tap.
   ============================================================================ */

.liq-check-lead {
  font-size: 16px;
  font-weight: 600;
  color: var(--text-primary);
  margin-bottom: 14px;
}

.liq-check-field {
  display: block;
  margin-top: 12px;
}

.liq-check-field span {
  display: block;
  font-size: 13px;
  color: var(--text-secondary);
  margin-bottom: 4px;
}

.liq-check-field .form-input {
  width: 100%;
}

/* Clearance above the submit. The fields space themselves with
   margin-top, but whatever follows the last one gets nothing - so
   "Start the day" sat flush against the derail input, reading as part
   of it and sitting one mis-tap from the text box.

   Sibling rules rather than a class on the button: it is a platform
   .btn, and giving every .btn in the product a top margin to fix one
   screen is how a stylesheet rots. .liq-cscale is covered too, since
   the field order differs between the morning and the evening. */
.liq-check-field + button,
.liq-check-field + .btn,
.liq-check-field + .btn-block,
.liq-cscale + button,
.liq-cscale + .btn,
.liq-cscale + .btn-block {
  margin-top: 22px;
}

.liq-cscale {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-top: 12px;
}

.liq-cscale-label {
  font-size: 14px;
  color: var(--text-secondary);
}

.liq-cscale-btns {
  display: flex;
  gap: 5px;
}

.liq-cscale-wide {
  flex-direction: column;
  align-items: stretch;
  gap: 6px;
  margin-top: 16px;
}

.liq-cscale-wide .liq-cscale-btns {
  display: flex;
}

.liq-cscale-wide .liq-cscale-btn {
  flex: 1 1 0;
}

.liq-cscale-btn {
  min-width: var(--touch-target-touch, 44px);
  min-height: var(--touch-target-touch, 44px);
  background: var(--bg-raised);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  color: var(--text-secondary);
  font-family: var(--font-ui);
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

.liq-cscale-btn.is-on {
  background: var(--accent-dim);
  border-color: var(--accent-bord);
  color: var(--accent);
}

.liq-check-q {
  font-size: 17px;
  font-weight: 600;
  color: var(--text-primary);
  line-height: 1.45;
  margin-bottom: 12px;
}

.liq-check-answer {
  width: 100%;
  resize: vertical;
}

.liq-check-answer-read {
  font-size: 15px;
  color: var(--text-secondary);
  line-height: 1.6;
  margin-bottom: 14px;
}

.liq-check-read {
  border-top: 1px solid var(--border);
  padding-top: 10px;
}

.liq-read-row {
  display: flex;
  justify-content: space-between;

  /* Sentences live in this row too - Intent and Risk. With no gap the
     value fills the width, space-between has nothing left to distribute,
     and the label welds to the first word. */
  gap: 14px;

  font-size: 14px;
  padding: 5px 0;
  color: var(--text-secondary);
}

/* The label never shrinks; the value takes what is left. */
.liq-read-row span:first-child {
  flex: 0 0 auto;
}

.liq-read-row span:last-child {
  flex: 1 1 auto;

  /* A flex item defaults to min-width:auto and refuses to wrap below its
     longest word, which pushes the row wider than the card. */
  min-width: 0;
  text-align: right;
  color: var(--text-primary);
}

.liq-check-dragon {
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px solid var(--border);
  font-size: 15px;
  color: var(--text-primary);
}

.liq-check-dragon-label {
  display: block;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.06em;
  color: var(--dragon);
  margin-bottom: 3px;
}

.liq-check-outcome {
  font-size: 13px;
  color: var(--signal);
}

.liq-outcome-open {
  color: var(--text-dim);
}


/* ============================================================================
   Install bar
   Sits above the bottom tab bar so it never covers navigation. Only
   ever shown after a few visits, and dismissing it is permanent.
   ============================================================================ */

.liq-install {
  position: fixed;
  left: 12px;
  right: 12px;
  bottom: calc(var(--tabbar-h, 56px) + 12px + env(safe-area-inset-bottom, 0px));
  z-index: var(--z-toast, 900);
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 14px;
  background: var(--bg-overlay);
  border: 1px solid var(--accent-bord);
  border-radius: var(--radius-lg, 14px);
  box-shadow: var(--shadow-toast, 0 8px 24px rgba(0,0,0,0.35));
}

/* ============================================================================
   Platform override: toast clearance.

   .iq-toast is fixed at bottom:24px and the tab bar is 56px tall and
   also fixed, so every toast landed on top of navigation. Overridden
   here rather than in components.css because the tab bar is a PRODUCT
   feature - the product created the collision, the product owns the
   fix, and components.css stays clean for the next product that has no
   tab bar. Same calc() .liq-install has always used.
   ============================================================================ */

.iq-toast {
  bottom: calc(var(--tabbar-h, 56px) + 16px + env(safe-area-inset-bottom, 0px));
}

/* Desktop has a sidebar and no tab bar, so the toast goes back down. */
@media (pointer: fine) {

  .iq-toast {
    bottom: 24px;
  }

}

.liq-install-text {
  flex: 1 1 auto;
  font-size: 14px;
  line-height: 1.45;
  color: var(--text-primary);
}

.liq-install-go {
  flex: 0 0 auto;
  min-height: var(--touch-target-touch, 44px);
  padding: 9px 16px;
  background: var(--accent);
  border: 0;
  border-radius: var(--radius);
  color: var(--bg-base);
  font-family: var(--font-ui);
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
}

.liq-install-x {
  flex: 0 0 auto;
  min-width: var(--touch-target-min, 40px);
  min-height: var(--touch-target-min, 40px);
  background: none;
  border: 0;
  color: var(--text-dim);
  font-size: 22px;
  line-height: 1;
  cursor: pointer;
}


/* ============================================================================
   Identity
   ============================================================================ */

.liq-ident-lead {
  font-size: 14px;
  color: var(--text-secondary);
  line-height: 1.6;
}

.liq-ident-input {
  width: 100%;
  resize: vertical;
  line-height: 1.6;
  margin-bottom: 12px;
}

.liq-ident-meta {
  font-size: 12px;
  color: var(--text-dim);
  margin-bottom: 10px;
}

.liq-ident-raw {
  font-size: 15px;
  color: var(--text-primary);
  line-height: 1.65;
  white-space: pre-wrap;
}

.liq-ident-sec {
  padding: 12px 14px;
  border-bottom: 1px solid var(--border);
}

.liq-ident-sec:last-child {
  border-bottom: 0;
}

/* A section switched out of the prompt is still stored, so it reads as
   dimmed rather than deleted. */
.liq-ident-sec.is-off {
  opacity: 0.45;
}

.liq-ident-sec-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 5px;
}

.liq-ident-sec-label {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.05em;
  color: var(--text-dim);
  text-transform: uppercase;
}

.liq-ident-sec-body {
  font-size: 14px;
  color: var(--text-secondary);
  line-height: 1.6;
  white-space: pre-wrap;
}

.liq-toggle {
  min-width: 46px;
  min-height: var(--touch-target-min, 40px);
  padding: 5px 12px;
  background: var(--bg-raised);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  color: var(--text-dim);
  font-family: var(--font-ui);
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

.liq-toggle.is-on {
  background: var(--signal-dim);
  border-color: var(--signal-bord);
  color: var(--signal);
}

.liq-hist-row {
  padding: 12px 14px;
  border-bottom: 1px solid var(--border);
}

.liq-hist-row:last-child {
  border-bottom: 0;
}

.liq-hist-meta {
  font-size: 12px;
  color: var(--text-dim);
  margin-bottom: 5px;
}

.liq-hist-text {
  font-size: 13px;
  color: var(--text-secondary);
  line-height: 1.55;
  white-space: pre-wrap;
  max-height: 140px;
  overflow-y: auto;
}


/* ============================================================================
   Memory
   ============================================================================ */

.liq-mem-note {
  font-size: 13px;
  color: var(--text-dim);
  margin: -4px 0 10px;
}

.liq-mem-count {
  color: var(--text-dim);
  font-weight: 400;
}

/* .liq-mem, .liq-mem-body, .liq-mem-text, .liq-mem-type and the
   standing/transient badges are defined in the Memory management block
   above. Only the additions the list view needs are here. */

.liq-mem-body[data-act] {
  cursor: pointer;
}

.liq-mem-prune {
  display: flex;
  gap: 8px;
}

.liq-mem-prune .btn {
  flex: 1 1 0;
}
/* ==========================================================================
   Tasks screen -- rebuilt to Tasks IQ parity (tasks.js 2.0.0)
   Quick add, scope tabs, signal strip, task row parts, subtask panel,
   and the full-screen editor. Row grid itself is defined above on
   .liq-task; everything here fills its tracks.
   ========================================================================== */

.liq-quickadd {
  display: flex;
  gap: 8px;
  margin-bottom: 12px;
}

/* min-width:0 matters: a flex item defaults to min-width:auto and an
   input refuses to shrink below its intrinsic size, which pushes the
   button off the right edge on a narrow phone. */
.liq-quickadd .form-input { flex: 1 1 auto; min-width: 0; }

/* One button, labelled. It was a bare right-arrow beside a bare plus,
   doing different things, with nothing on screen saying which was
   which. width is auto so the word fits; the height floor stays. */
.liq-qa-go {
  flex: 0 0 auto;
  min-height: var(--touch-target-touch, 44px);
  padding: 0 18px;
  border-radius: var(--radius);
  cursor: pointer;
  font-size: var(--font-min-body, 14px);
  font-weight: 600;
  line-height: 1;
  white-space: nowrap;
  background: var(--accent);
  border: 1px solid var(--accent);
  color: var(--bg-base);
  -webkit-tap-highlight-color: transparent;
}

/* Scope tabs -------------------------------------------------------------- */

.liq-scope-tabs {
  display: flex;
  gap: 6px;
  margin-bottom: 12px;
}

.liq-scope-tab {
  flex: 1 1 0;
  min-height: var(--touch-target-min);
  padding: 6px 10px;
  background: transparent;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  color: var(--text-secondary);
  font-family: var(--font-display);
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  cursor: pointer;
}

.liq-scope-tab.active {
  background: var(--bg-raised);
  border-color: var(--accent-bord);
  color: var(--accent);
}

/* Signal count strip ------------------------------------------------------ */

.liq-sig-strip {
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
  margin-bottom: 10px;
  padding: 0 2px;
  font-size: var(--font-min-secondary);
  color: var(--text-secondary);
}

.liq-sig-count {
  display: inline-flex;
  align-items: center;
  gap: 5px;
}

.liq-sig-count b { color: var(--text-primary); }

/* Signal diamond ---------------------------------------------------------- */

.liq-diamond {
  display: inline-block;
  width: 10px;
  height: 10px;
  transform: rotate(45deg);
  border-radius: 2px;
  flex: 0 0 auto;
}

.liq-diamond-signal       { background: var(--signal); }
.liq-diamond-necessary    { background: var(--necessary); }
.liq-diamond-noise        { background: var(--noise); }

/* Hollow, not a fourth colour: an untriaged screen should look unfinished. */
.liq-diamond-unclassified {
  background: transparent;
  border: 1.5px solid var(--unclassified-ring);
}

/* Task row parts ---------------------------------------------------------- */

.liq-tasklist {
  border-top: 1px solid var(--border);
  /* The list scrolls down, never across. */
  max-width: 100%;
  overflow-x: clip;
}

/* Visible enough to find, quiet enough to ignore. It was --text-dim at
   13px, which on a phone read as nothing at all - and a control nobody
   can see is a control nobody knows they have. The hit area is the
   full row height so a drag can start anywhere down the left edge
   rather than only on two tiny glyphs. */
.liq-handle {
  display: flex;
  align-items: center;
  justify-content: center;
  align-self: stretch;
  min-height: var(--touch-target-touch, 44px);
  margin: -12px 0;
  color: var(--text-secondary);
  font-size: 15px;
  line-height: 1;
  letter-spacing: -3px;
  cursor: grab;
  user-select: none;
  -webkit-user-select: none;
  touch-action: none;
  -webkit-tap-highlight-color: transparent;
}

.liq-handle:active {
  color: var(--accent);
  cursor: grabbing;
}

/* Used by the Tasks grid AND by Today's flex rows. flex:0 0 auto and
   the explicit width matter for the flex case - in the grid the track
   sizes it, in a flex row nothing would. */
.liq-cell-sig {
  display: flex;
  flex: 0 0 auto;
  align-items: center;
  justify-content: center;
  width: 14px;
  margin-top: 7px;
}

/* In the Tasks grid the track owns the width and the row is centred,
   so the flex-row nudge has to come back off. */
.liq-task .liq-cell-sig {
  width: auto;
  margin-top: 0;
}

.liq-task-main {
  min-width: 0;
  cursor: pointer;
}

.liq-task-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  margin-top: 3px;
  font-size: var(--font-min-display);
  color: var(--text-dim);
  min-width: 0;
}

/* Meta tokens wrap as whole items or not at all. A date is one thing;
   "2026-" on one line and "07-26" on the next is not a date. */
.liq-task-meta > * {
  white-space: nowrap;
}

.liq-meta-cat {
  display: inline-flex;
  align-items: center;
  gap: 5px;
}

.liq-swatch {
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: 999px;
}

.liq-meta-defer { color: var(--dragon); }

/* The mark is the product's one piece of iconography and it appears in
   two places that want very different sizes: the DRAGON OF THE DAY card
   heading, where it is the thing your eye lands on first, and a task
   row, where it is a tag on one line among twenty.

   A single rule served both, and the row won - which is why the card
   heading carried an 18px orange smudge next to it. The base size is
   now the card's, and rows step it back down. */
.liq-dragon-mark {
  display: inline-flex;
  flex: 0 0 auto;
  align-items: center;

  /* Only reached if IQ.icons.dragon is ever a text glyph rather than
     SVG. Kept in step with the svg rule so the fallback is not a
     surprise. */
  font-size: 30px;
  line-height: 1;
  color: var(--dragon, var(--accent));
}

.liq-dragon-mark svg {
  width: 34px;
  height: 34px;
  display: block;
}

/* In a list the mark identifies a row, it does not headline it. 26px
   clears the 32px importance track on the Tasks grid without widening
   it, so the row layout is untouched. */
.liq-task .liq-dragon-mark svg,
.liq-row .liq-dragon-mark svg {
  width: 26px;
  height: 26px;
}

.liq-task .liq-dragon-mark,
.liq-row .liq-dragon-mark {
  font-size: 22px;
}

/* The only way into the subtask panel, and it was a 14px glyph in 4px
   of padding - roughly 22px square, half the touch floor. Fixed width
   so a "0/6" row and a bare triangle occupy the same track. */
.liq-chev {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  min-height: var(--touch-target-touch, 44px);
  padding: 0;
  border: none;
  background: transparent;
  color: var(--text-dim);
  font-family: var(--font-display, inherit);

  /* The target was 44px and correct; the glyph was 14px and was not, so
     the one control that opens the subtask panel read as a speck in a
     large empty space. */
  font-size: 20px;
  line-height: 1;
  cursor: pointer;
}

/* A count is information and a triangle is only an invitation to go and
   look - so when there is something in there, say what. Smaller than the
   triangle on purpose: a count is read, a triangle is aimed at. */
.liq-chev.has-subs {
  color: var(--text-secondary);
  font-size: 13px;
  letter-spacing: 0.02em;
}

.liq-hint {
  margin-top: 8px;
  font-size: var(--font-min-display);
  color: var(--text-dim);
}

/* Subtask panel ----------------------------------------------------------- */

/* ==========================================================================
   Subtask panel

   Indented to sit under the parent's title rather than the row's left
   edge, so the steps read as belonging to the task instead of as more
   tasks. Less indent on a phone: 64px of the 360 available is a fifth of
   the screen spent on saying "these are nested".
   ========================================================================== */

.liq-subpanel {
  padding: 8px 14px 12px 52px;
  border-bottom: 1px solid var(--border);
  background: var(--bg-surface);
}

/* Five children, always: handle, check, title, effort, remove. Fixed
   tracks for everything except the title so the effort selects line up
   down the panel - a ragged column of them is the same noise the task
   row had before the capsule. */
.liq-sub {
  display: grid;
  grid-template-columns: 18px 20px minmax(0, 1fr) 62px 28px;
  gap: 8px;
  align-items: center;
  padding: 3px 0;
}

.liq-sub.is-dragging {
  opacity: 0.55;
}

.liq-sub-handle {
  display: flex;
  align-items: center;
  justify-content: center;
  align-self: stretch;
  min-height: var(--touch-target-touch, 44px);
  color: var(--border-light, var(--border));
  font-size: 13px;
  line-height: 1;
  cursor: grab;

  /* Without this the browser claims the gesture for scrolling and the
     drag never starts on a phone. */
  touch-action: none;
}

.liq-check.sm {
  width: 20px;
  height: 20px;
  font-size: 12px;
}

.liq-sub-title {
  min-width: 0;
  font-size: var(--font-min-secondary);
  color: var(--text-secondary);
  overflow-wrap: break-word;
}

/* The whole row dims, not only the text. A completed step whose select
   and handle stay at full strength reads as half-finished. */
.liq-sub.is-done .liq-sub-title {
  color: var(--text-dim);
  text-decoration: line-through;
}

.liq-sub.is-done .liq-sub-eff,
.liq-sub.is-done .liq-sub-handle {
  opacity: 0.5;
}

/* Compact, and deliberately quiet. It is a control you use occasionally
   on a row you mostly just tick. */
.liq-sub-eff {
  width: 62px;
  min-height: 34px;
  padding: 0 20px 0 7px;
  background-position: right 4px center;
  font-size: var(--font-min-secondary, 13px);
}

.liq-sub-x {
  min-height: var(--touch-target-touch, 44px);
  padding: 0;
  border: none;
  background: transparent;
  color: var(--text-dim);
  font-size: 18px;
  line-height: 1;
  cursor: pointer;
}

/* Same five-track shape as a row, minus the handle and checkbox, so the
   new step's text box starts where the existing titles do and its
   effort select sits under theirs. */
.liq-sub-add {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 62px 58px;
  gap: 6px;
  margin-top: 8px;
}

.liq-sub-add .liq-sub-new {
  min-height: 40px;

  /* 16px or iOS zooms the page on focus - and this is the field a
     person uses six times in a row. */
  font-size: var(--font-min-body, 16px);
}

.liq-sub-add .liq-sub-addbtn {
  min-height: 40px;
  padding: 0 8px;
}

/* Only rendered when something totals. Phrased as what the steps ADD,
   because the parent keeps its own estimate and the two are summed - the
   line has to make that obvious or the number looks wrong. */
.liq-sub-total {
  margin: 10px 0 0;
  font-size: var(--font-min-secondary, 13px);
  color: var(--text-dim);
}

/* A rolled-up duration is a computed figure rather than the rung that
   was chosen, and it should be legible as such without a legend. */
.liq-effort.is-rolled {
  color: var(--accent-light, var(--accent));
  border-color: var(--accent-bord, var(--border));
}

/* Editor ------------------------------------------------------------------ */

/* Task editor sheet ------------------------------------------------------- */

/*
  Mobile-first: this is a bottom sheet by default and only becomes a
  centered panel where there is a mouse. The head and the foot are
  outside the scroll container deliberately - a software keyboard eats
  most of a phone viewport, and a Save button that scrolls away with the
  form is the reason the modal had to go.
*/
.liq-sheet-wrap {
  position: fixed;
  inset: 0;
  z-index: var(--z-modal, 400);
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
}

.liq-sheet-scrim {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.6);
}

.liq-sheet {
  position: relative;
  display: flex;
  flex-direction: column;
  width: 100%;
  max-height: 92vh;
  max-height: 92dvh;
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-bottom: 0;
  border-radius: var(--radius-lg, 14px) var(--radius-lg, 14px) 0 0;
  box-shadow: var(--shadow-modal, 0 16px 48px rgba(0, 0, 0, 0.4));
  animation: liq-sheet-up var(--transition-base, 180ms) ease-out;
}

@keyframes liq-sheet-up {
  from { transform: translateY(100%); }
  to   { transform: translateY(0); }
}

.liq-sheet-head {
  position: relative;
  flex: 0 0 auto;
  padding: 10px 16px 12px;
  border-bottom: 1px solid var(--border);
}

/* Affordance only. The sheet is not drag-dismissable; the X is. */
.liq-sheet-grab {
  display: block;
  width: 36px;
  height: 4px;
  margin: 0 auto 10px;
  border-radius: 999px;
  background: var(--border-light);
}

.liq-sheet-x {
  position: absolute;
  top: 8px;
  right: 8px;
  width: var(--touch-target-touch);
  height: var(--touch-target-touch);
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--text-secondary);
  font-size: 24px;
  line-height: 1;
  cursor: pointer;
}

.liq-sheet-body {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  padding: 4px 16px 16px;
}

.liq-sheet-foot {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 12px 16px calc(12px + env(safe-area-inset-bottom, 0px));
  border-top: 1px solid var(--border);
  background: var(--bg-surface);
}

.liq-sheet-foot .btn,
.liq-sheet-foot .liq-danger-btn {
  width: 100%;
  min-height: var(--touch-target-touch);
}

/* Locks the list behind the sheet. */
body.liq-sheet-open { overflow: hidden; }

.liq-modal-title {
  margin: 0;
  padding-right: var(--touch-target-touch);
  font-size: 20px;
  color: var(--text-primary);
}

.liq-sheet-body .form-label { margin-top: 14px; }

@media (pointer: fine) {

  .liq-sheet-wrap { justify-content: center; align-items: center; }

  .liq-sheet {
    width: calc(100% - 32px);
    max-width: 520px;
    max-height: 86vh;
    border: 1px solid var(--border);
    border-radius: var(--radius-lg, 14px);
    animation: none;
  }

  .liq-sheet-grab { display: none; }

  .liq-sheet-foot { flex-direction: row; justify-content: flex-end; }

  .liq-sheet-foot .btn,
  .liq-sheet-foot .liq-danger-btn { width: auto; min-width: 110px; }

  /* Delete sits away from Save so a mis-click is not destructive. */
  .liq-sheet-foot .liq-danger-btn { margin-right: auto; }
}

@media (prefers-reduced-motion: reduce) {
  .liq-sheet { animation: none; }
}

/* Login ------------------------------------------------------------------- */

/*
  .iq-login-wrap is a sibling of ##iq-root in index.cfm, not a child, so it
  inherits no height from the shell grid and shell.css's max-height:100%
  resolves against nothing. Given an explicit height its existing
  align-items:center starts working. Matches .riq-login-wrap in the
  Renewal IQ shell.
*/
.iq-login-wrap {
  min-height: 100vh;
  min-height: 100dvh;
  max-height: none;
  box-sizing: border-box;
}

/* Required-field flash ---------------------------------------------------- */

/*
  Applied for ~1.6s when Save is refused. Outline rather than border so
  nothing reflows - a picker that jumps as it highlights reads as a
  glitch rather than as an instruction.
*/
.is-missing {
  outline: 2px solid var(--yellow);
  outline-offset: 3px;
  border-radius: var(--radius-sm, 6px);
  animation: liq-missing-pulse 500ms ease-in-out 2;
}

@keyframes liq-missing-pulse {
  0%, 100% { outline-color: var(--yellow); }
  50%      { outline-color: transparent; }
}

@media (prefers-reduced-motion: reduce) {
  .is-missing { animation: none; }
}

/* Priority + signal pickers ----------------------------------------------- */

/*
  Priority has no default, so a new task opens with every dot empty.
  This hint sits inline in the label and is removed by _pickImp() the
  moment a value is chosen.
*/
.liq-req {
  margin-left: 6px;
  font-size: var(--font-min-secondary, 13px);
  font-weight: 400;
  color: var(--yellow);
  text-transform: none;
  letter-spacing: 0;
}

.liq-imp-pick {
  display: flex;
  gap: 10px;
}

.liq-imp-btn {
  width: 30px;
  height: 30px;
  border-radius: 999px;
  border: 1px solid var(--border-light);
  background: transparent;
  cursor: pointer;
}

.liq-imp-btn.on {
  background: var(--text-secondary);
  border-color: var(--text-secondary);
}

.liq-sig-pick {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.liq-sig-btn {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  min-height: var(--touch-target-min);
  padding: 6px 12px;
  background: transparent;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  color: var(--text-secondary);
  font-size: var(--font-min-secondary);
  cursor: pointer;
}

.liq-sig-btn.on {
  border-color: var(--accent-bord);
  background: var(--accent-dim);
  color: var(--text-primary);
}

/* Narrow phones: drop the handle track, reorder stays available on the
   wider layout. Keeping it would eat title width where it matters most. */
/* Touch widths. SEVEN tracks, same as desktop, because all seven
   children are present - the handle included. Nothing in this row is ever
   display:none: a hidden grid child is removed from track assignment
   entirely and every child after it shifts one column left, which is
   how the title once ended up rendering inside the 14px signal track.
   Tracks and children stay one-to-one at every width, permanently. */
@media (max-width: 600px) {

  .liq-task {
    grid-template-columns: 20px 28px 14px minmax(0, 1fr) auto auto;
    gap: 8px;
    padding: 12px 12px;
  }

  .liq-subpanel { padding-left: 46px; }

  /* A long title wraps as a last resort rather than forcing the row
     wide, but it has the whole row to work with first. */
  .liq-task-title {
    overflow-wrap: anywhere;
  }

}

/* ==========================================================================
   Settings -- category management (settings.js 1.3.0)
   Grid per row: colour | name | Google colour | delete. Fixed tracks so
   the name field is the only thing that flexes.
   ========================================================================== */

.liq-cat-note {
  margin: 0 2px 10px;
  font-size: var(--font-min-secondary);
  color: var(--text-secondary);
  line-height: 1.5;
}

.liq-cat-list { padding: 4px 0; }

.liq-cat-empty {
  padding: 16px;
  text-align: center;
  font-size: var(--font-min-secondary);
  color: var(--text-dim);
}

.liq-cat-row {
  display: grid;
  grid-template-columns: 40px 1fr 150px 34px;
  align-items: center;
  gap: 10px;
  padding: 8px 12px;
  border-bottom: 1px solid var(--border);
}

.liq-cat-row:last-child { border-bottom: none; }

.liq-cat-color {
  width: 40px;
  height: 34px;
  padding: 2px;
  background: transparent;
  border: 1px solid var(--border-light);
  border-radius: var(--radius);
  cursor: pointer;
}

.liq-cat-name,
.liq-cat-g {
  min-height: var(--touch-target-min);
  font-size: var(--font-min-body);
}

.liq-cat-x {
  width: 34px;
  height: 34px;
  background: transparent;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  color: var(--text-dim);
  font-size: 18px;
  line-height: 1;
  cursor: pointer;
}

.liq-cat-x:hover {
  color: var(--noise);
  border-color: var(--noise-bord);
}

.liq-cat-new {
  width: 100%;
  min-height: var(--touch-target-touch);
  margin-top: 8px;
}

/* Narrow phones: the Google colour select drops to its own line rather
   than squeezing the name field into uselessness. */
@media (max-width: 520px) {
  .liq-cat-row {
    grid-template-columns: 40px 1fr 34px;
    grid-template-areas:
      "color name x"
      "g     g    g";
    row-gap: 8px;
  }
  .liq-cat-color { grid-area: color; }
  .liq-cat-name  { grid-area: name; }
  .liq-cat-x     { grid-area: x; }
  .liq-cat-g     { grid-area: g; }
}


/* ============================================================================
   GOALS
   Month and quarter goals. The screen runs twelve and four times a year,
   so it is built to be unambiguous rather than fast - you will not have
   seen it for thirty days when it next appears.
   ============================================================================ */

.liq-goal-h {
  margin: 0 0 4px;
  font-size: 17px;
  color: var(--text-primary);
}

/* Period label. Sits inside the heading and in review rows. */
.liq-goal-per {
  color: var(--text-dim);
  font-size: var(--font-min-secondary, 13px);
  font-weight: 400;
}

.liq-goal-sub {
  margin: 0 0 12px;
  color: var(--text-secondary);
  font-size: var(--font-min-secondary, 13px);
}

.liq-goal-empty {
  margin: 8px 0 12px;
  color: var(--text-dim);
  font-size: var(--font-min-secondary, 13px);
}

/* -- A goal in its own period ---------------------------------------------- */

.liq-goal-row {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 10px 0;
  border-bottom: 1px solid var(--border);
}

.liq-goal-row:last-of-type { border-bottom: 0; }

.liq-goal-body {
  display: flex;
  flex-direction: column;
  gap: 3px;
  flex: 1 1 auto;
  min-width: 0;
}

.liq-goal-title {
  color: var(--text-primary);
  font-size: var(--font-min-body, 14px);
  line-height: 1.35;
}

.liq-goal-why {
  color: var(--text-dim);
  font-size: var(--font-min-secondary, 13px);
  line-height: 1.35;
}

.liq-goal-status {
  align-self: flex-start;
  margin-top: 2px;
  font-size: var(--font-min-display, 12px);
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--text-dim);
}

/* Status reuses the signal triad. A hit goal is signal, a missed one is
   noise - same vocabulary as every other screen. */
.liq-goal-hit .liq-goal-status,
.liq-goal-hit .liq-goal-title { color: var(--signal); }

.liq-goal-missed .liq-goal-status,
.liq-goal-missed .liq-goal-title { color: var(--noise); }

.liq-goal-dropped .liq-goal-title,
.liq-goal-dropped .liq-goal-status {
  color: var(--text-dim);
  text-decoration: line-through;
}

.liq-goal-del {
  flex: 0 0 auto;
  width: var(--touch-target-min, 40px);
  height: var(--touch-target-min, 40px);
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--text-dim);
  font-size: 20px;
  line-height: 1;
  cursor: pointer;
}

/* -- Close-out block ------------------------------------------------------- */

/* Deliberately loud. This is the block that has to be answered before
   anything new can be set. */
.liq-goal-review {
  border-color: var(--accent-bord);
}

.liq-goal-rrow {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  padding: 10px 0;
  border-bottom: 1px solid var(--border);
}

.liq-goal-rrow:last-of-type { border-bottom: 0; }

.liq-goal-rtext {
  display: flex;
  flex-direction: column;
  gap: 2px;
  flex: 1 1 180px;
  min-width: 0;
}

.liq-goal-racts {
  display: flex;
  gap: 8px;
  flex: 0 0 auto;
}

.liq-goal-hit,
.liq-goal-miss {
  min-height: var(--touch-target-touch, 44px);
  padding: 8px 16px;
  border-radius: var(--radius, 8px);
  background: transparent;
  font-size: var(--font-min-body, 14px);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

.liq-goal-hit {
  border: 1px solid var(--signal-bord, var(--signal));
  color: var(--signal);
}

.liq-goal-miss {
  border: 1px solid var(--noise-bord, var(--noise));
  color: var(--noise);
}

/* -- Add form -------------------------------------------------------------- */

.liq-goal-add {
  width: 100%;
  min-height: var(--touch-target-touch, 44px);
  margin-top: 8px;
  padding: 10px 14px;
  border: 1px dashed var(--border-light);
  border-radius: var(--radius, 8px);
  background: transparent;
  color: var(--accent);
  font-size: var(--font-min-body, 14px);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

/* ============================================================================
   Goal metric - the measurable half
   ============================================================================ */

/* Pace, not progress. The bar shows how far along the number is; the
   colour shows whether that is enough for the day of the period it is.
   The same 22 percent is fine on day 3 and a problem on day 24. */

.liq-goal-metric {
  margin-top: 8px;
  min-width: 0;
}

.liq-goal-bar {
  height: 6px;
  background: var(--bg-raised);
  border-radius: 999px;
  overflow: hidden;
  margin-bottom: 6px;
}

.liq-goal-fill {
  display: block;
  height: 100%;
  background: var(--accent);
  border-radius: 999px;
}

.liq-goal-fill.is-behind { background: var(--necessary); }
.liq-goal-fill.is-done   { background: var(--signal); }

.liq-goal-pace {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  min-width: 0;
}

/* The number is the control. Tapping it is how it moves - a once-a-week
   act that does not deserve a form. */
.liq-goal-num {
  min-width: 0;
  min-height: var(--touch-target-min, 40px);
  padding: 0;
  background: transparent;
  border: 0;
  color: var(--text-secondary);
  font-family: inherit;
  font-size: 12px;
  text-align: left;
  cursor: pointer;
}

.liq-goal-num b {
  color: var(--text-primary);
  font-size: 14px;
}

.liq-goal-pacelbl {
  flex: 0 0 auto;
  font-size: 12px;
  color: var(--text-dim);
}

.liq-goal-pacelbl.is-on     { color: var(--signal); }
.liq-goal-pacelbl.is-behind { color: var(--necessary); }
.liq-goal-pacelbl.is-done   { color: var(--signal); }

/* Only shown once the goal is actually unreachable at the current rate.
   Said every day it would stop being read. */
.liq-goal-warn {
  margin-top: 6px;
  padding: 7px 9px;
  background: var(--bg-raised);
  border-left: 2px solid var(--necessary);
  border-radius: 4px;
  font-size: 12px;
  color: var(--text-secondary);
  line-height: 1.45;
}

.liq-goal-stale {
  margin-top: 5px;
  font-size: 12px;
  color: var(--text-dim);
}

/* A goal with no number. Not an error - it saved on purpose - so it
   gets a dashed edge and an offer rather than a red box. */
.liq-goal-vague {
  margin-top: 8px;
  padding: 8px 10px;
  border: 1px dashed var(--border-light, var(--border));
  border-radius: 6px;
  font-size: 12px;
  color: var(--text-dim);
  line-height: 1.5;
}

.liq-goal-link {
  display: inline-block;
  margin-top: 6px;
  min-height: var(--touch-target-min, 40px);
  padding: 0 10px;
  background: var(--accent-dim);
  border: 1px solid var(--accent-bord);
  border-radius: 6px;
  color: var(--accent-light);
  font-family: inherit;
  font-size: 12px;
  cursor: pointer;
}

/* ---- metric fields on the add form ---- */

.liq-goal-mfields {
  margin-top: 12px;
  padding: 12px;
  background: var(--accent-dim);
  border: 1px solid var(--accent-bord);
  border-radius: 8px;
}

.liq-goal-mhead {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 8px;
  font-size: 13px;
  font-weight: 600;
  color: var(--accent-light);
}

.liq-goal-mhead span {
  font-weight: 400;
  font-size: 11px;
  color: var(--text-dim);
}

/* Three tracks, three children, at every width. A grid child that
   disappears shifts every later child one track left. */
.liq-goal-mgrid {
  display: grid;
  grid-template-columns: 1fr 32px 1fr;
  gap: 6px;
  align-items: end;
}

.liq-goal-marrow {
  text-align: center;
  color: var(--text-dim);
  padding-bottom: 12px;
}

.liq-goal-form { margin-top: 10px; }

.liq-goal-facts {
  display: flex;
  gap: 8px;
  margin-top: 12px;
}

.liq-goal-facts .btn {
  flex: 1 1 auto;
  min-height: var(--touch-target-touch, 44px);
}

.liq-goal-done { margin: 4px 0 24px; }

.liq-goal-done .btn {
  width: 100%;
  min-height: var(--touch-target-touch, 44px);
}


/* ============================================================================
   Mood
   ============================================================================ */

/* Two tiers: a scale, then words that belong to where you landed. The
   scale carries magnitude, the words carry texture, and neither
   substitutes for the other - annoyed and wrecked are both unpleasant.

   Shapes, not emoji. Emoji ignore currentColor and render in the
   platform palette, which is how a dragon came out green on an orange
   card in session 5. */

.liq-moment-btn--mood {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.liq-mood-sheet {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  background: rgba(0, 0, 0, 0.55);
  padding: 16px;
}

.liq-mood-panel {
  width: 100%;
  max-width: 420px;
  padding: 20px;
  background: var(--bg-elevated, var(--bg-surface));
  border: 1px solid var(--border);
  border-radius: 12px;

  /* Clear of the tab bar and the iOS home indicator. */
  margin-bottom: calc(var(--tabbar-h, 56px) + env(safe-area-inset-bottom, 0px));
}

.liq-mood-ask {
  margin: 0 0 14px;
  font-size: 16px;
  font-weight: 600;
  color: var(--text-primary);
}

/* Five children, five tracks, at every width. */
.liq-mood-scale {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 6px;
}

.liq-mood-dot {
  min-height: var(--touch-target-touch, 44px);
  padding: 0;
  background: var(--bg-raised);
  border: 1px solid var(--border);
  border-radius: 8px;
  color: var(--text-dim);
  font-size: 15px;
  line-height: 1;
  cursor: pointer;
}

.liq-mood-dot.vn2 { color: var(--noise); }
.liq-mood-dot.vn1 { color: var(--necessary); }
.liq-mood-dot.vp0 { color: var(--text-dim); }
.liq-mood-dot.vp1 { color: var(--accent); }
.liq-mood-dot.vp2 { color: var(--signal); }

.liq-mood-dot.is-on {
  border-color: var(--accent);
  background: var(--accent-dim);
}

.liq-mood-lbl {
  margin: 8px 0 0;
  text-align: center;
  font-size: 13px;
  color: var(--text-secondary);
}

.liq-mood-words {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 14px;
}

.liq-mood-word {
  min-height: var(--touch-target-min, 40px);
  padding: 0 12px;
  background: transparent;
  border: 1px solid var(--border);
  border-radius: 999px;
  color: var(--text-secondary);
  font-family: inherit;
  font-size: 13px;
  cursor: pointer;
}

.liq-mood-word.is-on {
  background: var(--accent-dim);
  border-color: var(--accent-bord);
  color: var(--accent-light);
}

.liq-mood-acts {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 8px;
  margin-top: 18px;
}

.liq-mood-btn {
  min-height: var(--touch-target-touch, 44px);
  padding: 0 16px;
  background: transparent;
  border: 1px solid var(--border);
  border-radius: 8px;
  color: var(--text-secondary);
  font-family: inherit;
  font-size: 14px;
  cursor: pointer;
}

.liq-mood-btn.is-primary {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--bg-base);
}

.liq-mood-btn[disabled] {
  opacity: 0.45;
  cursor: default;
}

.liq-mood-btn.is-quiet {
  border-color: transparent;
  color: var(--text-dim);
}


/* ============================================================================
   Streak strip - the only surface that shows what you have built
   ============================================================================ */

/* Every other screen shows an obligation. This shows accumulation, which
   is the thing that makes anything worth coming back to.

   A cell is filled by a CLOSE, never by a good day. No colour grading,
   no gold cell for a slain dragon - the moment a bad day threatens the
   strip, bad days stop getting closed, and then the app only holds
   records of good weeks. */

/* One alias, one place to retune. The amber is the app's --necessary,
   borrowed rather than invented: it already means "attention here",
   which is exactly what an unfinished day is, and it appears nowhere
   else on this row so there is no signal diamond beside it to collide
   with. If it ever needs to diverge from --necessary, this is the only
   line that changes. */
.liq-streak {
  --liq-today-ring: var(--necessary, #eab308);

  margin: 0 2px 14px;
  min-width: 0;
}

/* Twenty-one children, twenty-one tracks, at every width. Never
   display:none a grid child - it leaves track assignment and shifts
   every later child one column left. */
.liq-streak-cells {
  display: grid;
  grid-template-columns: repeat(21, 1fr);
  gap: 3px;
  margin-bottom: 6px;
}

.liq-streak-cell {
  display: block;
  width: 100%;
  aspect-ratio: 1 / 1;
  min-height: 14px;
  padding: 0;
  background: var(--bg-raised);
  border: 1px solid transparent;
  border-radius: 3px;
}

.liq-streak-cell.is-closed {
  background: var(--accent);
}

/* Three states, and every cell in the strip can be in any of them:

     blank   never started
     amber   opened and not closed
     blue    closed

   The classes are mutually exclusive by construction - today.js emits
   is-closed OR is-open, never both - so there is no precedence to
   express here and no way for a blue cell to also carry a ring.

   2px, not 1px. On a 14px square with a 3px gap a 1px ring reads as a
   tint rather than an outline. box-sizing is border-box app-wide, so
   the ring eats into the cell rather than growing it and the
   twenty-one tracks stay identical at every width. */
.liq-streak-cell.is-open {
  border-width: 2px;
  border-style: solid;
  border-color: var(--liq-today-ring);
}

/* is-today carries no colour. It survives only because the cell is a
   button on today and a span everywhere else, and the pointer belongs
   on the one that acts - a cursor on a cell that does nothing when
   tapped teaches you to stop tapping. */
.liq-streak-cell.is-today:not(.is-closed) {
  cursor: pointer;
}

.liq-streak-line {
  margin: 0;
  font-size: 12px;
  color: var(--text-dim);
}

/* ============================================================================
   Sayings editor
   ============================================================================ */

.liq-say-load {
  padding: 12px 2px;
  font-size: 13px;
  color: var(--text-dim);
}

.liq-say-rot {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 8px 10px;
  align-items: center;
  padding: 12px;
  margin-bottom: 12px;
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: 8px;
}

.liq-say-note {
  grid-column: 1 / -1;
  margin: 2px 0 0;
  font-size: 12px;
  line-height: 1.5;
  color: var(--text-dim);
}

.liq-say-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.liq-say {
  min-width: 0;
  padding: 12px;
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-left: 3px solid var(--accent);
  border-radius: 8px;
}

/* Retired, not deleted. Dimmed rather than hidden, because a line you
   are tired of in August may be the one you need in November. */
.liq-say.is-off {
  border-left-color: var(--border);
  opacity: 0.55;
}

.liq-say-text {
  width: 100%;
  resize: vertical;
  min-height: 56px;
  margin-bottom: 8px;
}

.liq-say-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  margin-bottom: 8px;
  min-width: 0;
}

.liq-say-row .form-input {
  min-width: 0;
  flex: 1 1 120px;
}

.liq-say-lbl {
  flex: 0 0 auto;
  font-size: 12px;
  color: var(--text-dim);
}

.liq-say-and {
  flex: 0 0 auto;
  font-size: 12px;
  color: var(--text-dim);
}

.liq-say-hr,
.liq-say-w {
  flex: 0 1 auto;
  min-width: 96px;
}

.liq-say-ord {
  flex: 0 0 72px;
}

.liq-say-acts {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  min-width: 0;
}

.liq-say-meta {
  flex: 1 1 auto;
  min-width: 0;
  font-size: 12px;
  color: var(--text-dim);
}

.liq-say-btn {
  flex: 0 0 auto;
  min-height: var(--touch-target-min, 40px);
  padding: 0 12px;
  background: transparent;
  border: 1px solid var(--border);
  border-radius: 6px;
  color: var(--text-secondary);
  font-family: inherit;
  font-size: 12px;
  cursor: pointer;
}

.liq-say-btn.is-danger {
  color: var(--noise);
  border-color: var(--border);
}

.liq-say-new {
  width: 100%;
  margin-top: 10px;
}

@media (max-width: 600px) {

  .liq-say-rot {
    grid-template-columns: 1fr;
  }

  .liq-say-row .form-input,
  .liq-say-hr,
  .liq-say-w {
    flex: 1 1 100%;
  }

  .liq-say-ord {
    flex: 1 1 100%;
  }
}


/* The opener is Wingman's read of the morning check-in, so it says so.
   Unattributed, that text reads as an accusation from nowhere - which
   is exactly how it read on Today. */
.liq-opener-note {
  margin: -4px 0 12px 4px;
  font-size: 12px;
  color: var(--text-dim);
}


/* ============================================================================
   Sayings screen
   ============================================================================ */

/* Three levels, each a full screen: buckets, list, editor. Pushing a
   whole screen rather than expanding a panel in place is what makes this
   workable one-thumbed - and there are no hour dropdowns anywhere, which
   was the worst control in the version this replaces. */

.liq-say2 {
  display: flex;
  flex-direction: column;
  padding-bottom: calc(var(--tabbar-h, 56px) + 20px);
  min-width: 0;
}

.liq-say2-load,
.liq-say2-none {
  padding: 22px 4px;
  color: var(--text-dim);
  font-size: 13.5px;
  text-align: center;
}

.liq-say2-top {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 0 0 16px;
  min-width: 0;
}

.liq-say2-h {
  flex: 1 1 auto;
  min-width: 0;
  margin: 0;
  font-family: var(--font-display, inherit);
  font-size: 21px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.liq-say2-back,
.liq-say2-link {
  flex: 0 0 auto;
  min-height: var(--touch-target-touch, 44px);
  padding: 0 10px;
  background: transparent;
  border: 0;
  color: var(--accent-light);
  font-family: inherit;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

/* The back button was a bare chevron: 44px tall and about 24px wide, so
   the actual target was a quarter of what it looked like. It now carries
   a word, a border and a real minimum width - and the border matters as
   much as the size, because a target you cannot see the edges of is one
   you aim at by guessing. */
.liq-say2-back {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  min-width: 88px;
  min-height: 48px;
  padding: 0 14px 0 10px;
  border: 1px solid var(--border);
  border-radius: 10px;
  font-size: 15px;
  line-height: 1;
}

.liq-say2-back:active {
  background: var(--accent-dim);
  border-color: var(--accent-bord);
}

.liq-say2-chev {
  font-size: 22px;
  line-height: 1;

  /* Optical, not mathematical: a chevron sits high in its box and reads
     as misaligned against text unless it is nudged down. */
  position: relative;
  top: -1px;
}

.liq-say2-link {
  font-size: 14px;
  min-width: 64px;
  min-height: 48px;
}

/* ---- level 1: buckets ---- */

.liq-bkt {
  display: flex;
  align-items: center;
  gap: 13px;
  width: 100%;
  margin-bottom: 10px;
  padding: 14px;
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: 13px;
  text-align: left;
  font-family: inherit;
  cursor: pointer;
}

/* An empty bucket is a finding, not an error. Dashed, not red. */
.liq-bkt.is-empty { border-style: dashed; }
.liq-bkt.is-empty .liq-bkt-nm,
.liq-bkt.is-empty .liq-bkt-ct { color: var(--text-dim); }

.liq-bkt-ic {
  flex: 0 0 42px;
  height: 42px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 11px;
  font-size: 18px;
  background: var(--bg-raised);
  color: var(--text-dim);
}

.liq-bkt-ic--morning   { background: var(--necessary-dim, rgba(234,179,8,.16)); color: var(--necessary); }
.liq-bkt-ic--afternoon { background: var(--bg-raised); color: var(--text-secondary); }
.liq-bkt-ic--evening   { background: var(--signal-dim, rgba(34,197,94,.16)); color: var(--signal); }
.liq-bkt-ic--late      { background: var(--accent-dim); color: var(--accent-light); }
.liq-bkt-ic--any       { background: var(--bg-raised); color: var(--text-dim); }

.liq-bkt-tx { flex: 1 1 auto; min-width: 0; }

.liq-bkt-nm {
  display: block;
  font-size: 15px;
  font-weight: 600;
  color: var(--text-primary);
  line-height: 1.2;
}

.liq-bkt-sb {
  display: block;
  margin-top: 3px;
  font-size: 12px;
  color: var(--text-dim);
}

.liq-bkt-ct {
  flex: 0 0 auto;
  font-family: var(--font-display, inherit);
  font-size: 22px;
  color: var(--text-secondary);
}

/* ---- level 2: one bucket's list ---- */

.liq-sq {
  display: flex;
  gap: 11px;
  width: 100%;
  padding: 14px 4px;
  background: transparent;
  border: 0;
  border-bottom: 1px solid var(--border);
  text-align: left;
  font-family: inherit;
  cursor: pointer;
}

/* Retired stays visible but dimmed. Hidden would make it unfindable,
   and the point of retiring rather than deleting is that you can get it
   back. */
.liq-sq.is-off { opacity: 0.45; }

.liq-sq-tx { flex: 1 1 auto; min-width: 0; }

.liq-sq-words {
  display: block;
  font-size: 14px;
  line-height: 1.5;
  color: var(--text-primary);
  overflow-wrap: anywhere;
}

.liq-sq-meta {
  display: block;
  margin-top: 6px;
  font-size: 11.5px;
  color: var(--text-dim);
}

.liq-sq-ch {
  flex: 0 0 auto;
  padding-top: 2px;
  color: var(--text-dim);
  font-size: 15px;
}

/* ---- level 3: the editor ---- */

.liq-say2-lbl {
  display: block;
  margin: 18px 0 7px;
  font-size: 11px;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--text-dim);
}

.liq-say2-ta,
.liq-say2-in {
  width: 100%;
  background: var(--bg-raised);
  border: 1px solid var(--border-light);
  border-radius: 10px;
  padding: 12px;
  color: var(--text-primary);
  font-family: inherit;
  line-height: 1.5;
}

/* 16px minimum on inputs. Anything smaller and iOS zooms the page on
   focus, which throws the layout and is a nuisance to get back from. */
.liq-say2-ta { min-height: 104px; font-size: 16px; resize: vertical; }
.liq-say2-in { min-height: 48px;  font-size: 16px; }

.liq-seg {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
}

.liq-seg--3 { grid-template-columns: 1fr 1fr 1fr; }

.liq-sg {
  min-height: 54px;
  padding: 6px 8px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  background: var(--bg-raised);
  border: 1px solid var(--border);
  border-radius: 10px;
  color: var(--text-secondary);
  font-family: inherit;
  font-size: 13.5px;
  line-height: 1.25;
  text-align: center;
  cursor: pointer;
}

.liq-sg small {
  font-size: 10.5px;
  color: var(--text-dim);
}

.liq-sg.is-on {
  background: var(--accent-dim);
  border-color: var(--accent);
  color: var(--accent-light);
}

.liq-sg.is-on small { color: var(--accent-light); opacity: 0.75; }

.liq-say2-big {
  width: 100%;
  min-height: 52px;
  margin-top: 16px;
  background: var(--accent);
  border: 1px solid var(--accent);
  border-radius: 11px;
  color: var(--bg-base);
  font-family: inherit;
  font-size: 15px;
  font-weight: 600;
  cursor: pointer;
}

.liq-say2-foot {
  display: flex;
  gap: 8px;
  margin-top: 26px;
}

.liq-say2-ghost {
  flex: 1 1 0;
  min-height: 48px;
  background: transparent;
  border: 1px solid var(--border-light);
  border-radius: 10px;
  color: var(--text-secondary);
  font-family: inherit;
  font-size: 13.5px;
  cursor: pointer;
}

.liq-say2-ghost.is-danger { color: var(--noise); }

.liq-say2-note {
  margin: 14px 0 0;
  font-size: 12px;
  line-height: 1.55;
  color: var(--text-dim);
}


/* ============================================================================
   Pulse - the read of the day so far
   ============================================================================ */

/* The wordmark is now a button. It sits centred in the topbar on every
   screen and was doing nothing. */
.iq-brand-center {
  background: transparent;
  border: 0;
  font-family: inherit;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

.iq-brand-center:active { opacity: 0.6; }

/* Above the tab bar, which is z-index 40. .iq-toast learned this the
   hard way: anything anchored to the bottom without accounting for the
   56px bar renders underneath navigation. */
.liq-pulse {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  background: rgba(0, 0, 0, 0.6);
  padding: 16px;
}

.liq-pulse-panel {
  width: 100%;
  max-width: 460px;
  padding: 18px;
  background: var(--bg-elevated, var(--bg-surface));
  border: 1px solid var(--border);
  border-radius: 14px;
  margin-bottom: calc(var(--tabbar-h, 56px) + env(safe-area-inset-bottom, 0px));
}

.liq-pulse-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 14px;
  font-family: var(--font-display, inherit);
  font-size: 14px;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--text-dim);
}

.liq-pulse-x {
  min-height: var(--touch-target-min, 40px);
  min-width: 40px;
  background: transparent;
  border: 0;
  color: var(--text-dim);
  font-size: 15px;
  cursor: pointer;
}

.liq-pulse-wait {
  margin: 0;
  padding: 22px 0;
  text-align: center;
  color: var(--text-dim);
  font-size: 13.5px;
}

.liq-pulse-read {
  margin: 0 0 16px;
  font-size: 15.5px;
  line-height: 1.6;
  color: var(--text-primary);
  overflow-wrap: anywhere;
}

/* The numbers the read was built from. Generated text can be wrong;
   facts underneath make a bad read visibly a bad read rather than
   something taken on faith. */
.liq-pulse-facts {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 6px;
  padding-top: 14px;
  border-top: 1px solid var(--border);
}

.liq-pulse-fact {
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  text-align: center;
}

.liq-pulse-fact b {
  font-family: var(--font-display, inherit);
  font-size: 18px;
  font-weight: 600;
  color: var(--text-primary);
  line-height: 1.1;
}

.liq-pulse-fact small {
  font-size: 10.5px;
  color: var(--text-dim);
  line-height: 1.25;
}

.liq-pulse-note {
  margin: 12px 0 0;
  font-size: 12px;
  line-height: 1.5;
  color: var(--necessary);
}

.liq-pulse-acts {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
  margin-top: 18px;
}

.liq-pulse-btn {
  min-height: var(--touch-target-touch, 44px);
  padding: 0 12px;
  background: transparent;
  border: 1px solid var(--border-light, var(--border));
  border-radius: 9px;
  color: var(--text-secondary);
  font-family: inherit;
  font-size: 14px;
  cursor: pointer;
}

.liq-pulse-btn.is-primary {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--bg-base);
}


/* ---- saying conditions ----------------------------------------------------

   Collapsed behind a toggle. Most sayings want none of these, and three
   pickers open by default would bury the words and the time window under
   settings nobody is using. */

.liq-cond-toggle {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  width: 100%;
  min-height: var(--touch-target-touch, 44px);
  margin-top: 22px;
  padding: 0 12px;
  background: transparent;
  border: 1px solid var(--border);
  border-radius: 10px;
  color: var(--text-secondary);
  font-family: inherit;
  font-size: 13.5px;
  text-align: left;
  cursor: pointer;
}

.liq-cond-toggle span {
  flex: 0 0 auto;
  max-width: 55%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--text-dim);
  font-size: 12px;
}

.liq-cond {
  margin-top: 10px;
  padding: 12px;
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: 10px;
}

.liq-cond-row {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 9px;
  min-width: 0;
}

.liq-cond-lbl {
  flex: 0 0 58px;
  font-size: 12.5px;
  color: var(--text-secondary);
}

/* Three children, three tracks, at every width. */
.liq-cond-opts {
  flex: 1 1 auto;
  min-width: 0;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 6px;
}

.liq-sg--sm {
  min-height: var(--touch-target-min, 40px);
  font-size: 12.5px;
  padding: 0 4px;
}


/* ---- mood, inside the day read -------------------------------------------

   It lived on Today as a bare button beside another bare button, and it
   took four explanations before anyone could say what either did. Here
   there is a question above it, and you arrived by asking the app how
   your day is going - so it asking back is the obvious next beat. */

.liq-pulse-mood {
  margin-top: 16px;
  padding-top: 14px;
  border-top: 1px solid var(--border);
}

.liq-pulse-moodq {
  margin: 0 0 10px;
  font-size: 13.5px;
  color: var(--text-secondary);
}

/* Five children, five tracks, at every width. */
.liq-pulse-scale {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 6px;
}

.liq-pulse-dot {
  min-height: var(--touch-target-touch, 44px);
  padding: 0;
  background: var(--bg-raised);
  border: 1px solid var(--border);
  border-radius: 9px;
  color: var(--text-dim);
  font-size: 14px;
  line-height: 1;
  cursor: pointer;
}

.liq-pulse-dot.vn2 { color: var(--noise); }
.liq-pulse-dot.vn1 { color: var(--necessary); }
.liq-pulse-dot.vp0 { color: var(--text-dim); }
.liq-pulse-dot.vp1 { color: var(--signal); }
.liq-pulse-dot.vp2 { color: var(--signal); }

.liq-pulse-dot:active {
  background: var(--accent-dim);
  border-color: var(--accent);
}

.liq-pulse-moodn {
  margin: 8px 0 0;
  font-size: 11.5px;
  color: var(--text-dim);
  text-align: center;
}


/* Condition rows now carry three bands each, not two plus Any - a middle
   value is a real value under scoring, where under the old filter it had
   to match nothing to keep the filter from swallowing ordinary days. */
.liq-cond-opts--3 { grid-template-columns: repeat(3, 1fr); }
.liq-cond-opts--2 { grid-template-columns: repeat(2, 1fr); }


/* ============================================================================
   Log form - when it happened
   ============================================================================ */

/* Dropdowns, not input type=time. A time input reports an empty string
   when it cannot parse what was typed, so a five-hour entry saved as
   zero and nothing on screen said why. A select cannot be in an
   unparseable state. */

.liq-when {
  margin: 12px 0;
  padding: 12px;
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: 10px;
}

.liq-when-row {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-bottom: 8px;
  min-width: 0;
}

/* 38px, not 46px. "From" fits in 38 at this size and the eight pixels
   are worth more to the three controls than to the word - at 360px
   every one of them counts twice, once for the value and once for the
   caret. */
.liq-when-lbl {
  flex: 0 0 38px;
  font-size: 13px;
  color: var(--text-secondary);
}

/* The padding SHORTHAND, a second time. forms.css sets
   select.form-input { padding-right: 40px } to clear the chevron it
   draws at right 14px, and a shorthand here reset it to 6px - so the
   caret sat on top of "00" and clipped it.

   This row is NOT IQ.dt. It is Reality's own From/To markup with its
   own classes, which is exactly why fixing .iq-dt in 1.44.0 did nothing
   for it. Both places are now explicit about all four sides; a grep for
   a padding shorthand on anything matching .form-input comes back
   clean. */
.liq-when-row .form-input {
  min-width: 0;
  min-height: var(--touch-target-touch, 44px);

  /* 16px or iOS zooms the page when a select is focused. */
  font-size: 16px;

  /* 40px of right padding is correct for a full-width select and absurd
     in a 75px one - it would leave nothing for the value. The chevron
     moves in to match: 16px wide at right 6px occupies 6-22px from the
     edge, and 24px of padding clears it by two. */
  padding: 0 24px 0 8px;
  background-position: right 6px center;
}

/* Three tracks, three children, at every width. The hour and minute
   lists are two characters wide; AM/PM needs a little more. */
/* The answer, computed. Asking for it a second time is what made the
   old form confusing - 10am to 3pm IS 300 minutes. */
.liq-when-total {
  /* Tracks the label width above it. */
  margin: 4px 0 0 44px;
  font-size: 15px;
  font-weight: 600;
  color: var(--accent-light);
}

.liq-when-dur {
  display: block;
  margin-bottom: 8px;
}

.liq-when-dur .form-input {
  width: 100%;
  min-height: var(--touch-target-touch, 44px);
  font-size: 16px;
}

.liq-when-swap {
  margin-top: 10px;
  min-height: var(--touch-target-min, 40px);
  padding: 0 4px;
  background: transparent;
  border: 0;
  color: var(--accent-light);
  font-family: inherit;
  font-size: 13px;
  text-decoration: underline;
  cursor: pointer;
}


/* ============================================================================
   IQ.dt - date and time dropdowns
   ============================================================================ */

/* Three tracks, three children, at every width. Native date and time
   inputs were replaced because they report an EMPTY string when the
   browser cannot parse them - a five-hour log entry saved as zero - and
   because they are miserable on a phone. */

.iq-dt {
  display: grid;
  /* Equal thirds, both variants. The uneven ratios existed to buy the
     month and year room back from the day - a problem created by the
     padding shorthand bug, not by the track widths, and fixed at its
     source in 1.44.0. Equal is enough for "Sep", "2026", "12", "45" and
     "PM" alike, and one rule beats two that have to be kept in step. */
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 6px;
  min-width: 0;
  margin-bottom: 12px;
}

/* padding is a SHORTHAND, and that is the whole bug. forms.css sets
   select.form-input { padding-right: 40px } to clear the chevron it
   draws at right 14px. A shorthand here reset that to 6px while the
   chevron stayed where it was, so the caret sat on top of the text in
   every IQ.dt dropdown in the app.

   Fixed by declaring all four sides deliberately and moving the chevron
   in to match. 40px of right padding is right for a full-width select;
   in a 70px-wide track it leaves almost nothing for the value. The
   chevron is 16px at right 6px, occupying 6-22px in from the edge, and
   24px of padding clears it. */
.iq-dt .form-input {
  min-width: 0;
  min-height: var(--touch-target-touch, 44px);
  padding: 0 24px 0 8px;
  background-position: right 6px center;

  /* 16px or iOS zooms the page when a select takes focus. */
  font-size: 16px;
}

/* The month name is the widest of the three; the day and year lists are
   two and four characters. */
.iq-dt-mo { grid-column: 1; }
.iq-dt-dy { grid-column: 2; }
.iq-dt-yr { grid-column: 3; }

.iq-dt-h  { grid-column: 1; }
.iq-dt-m  { grid-column: 2; }
.iq-dt-ap { grid-column: 3; }

/* ---- task difficulty ------------------------------------------------------

   A third axis, and separate from the other two on purpose: priority
   says what a task is worth, signal says what kind of work it is,
   difficulty says what it costs to start. The one that never gets done
   is important, signal, and hard. */

.liq-diff-pick {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 6px;
  margin-bottom: 14px;
}

.liq-diff-btn {
  min-height: var(--touch-target-touch, 44px);
  padding: 0 8px;
  background: var(--bg-raised);
  border: 1px solid var(--border);
  border-radius: 8px;
  color: var(--text-secondary);
  font-family: inherit;
  font-size: 14px;
  cursor: pointer;
}

.liq-diff-btn.on {
  background: var(--accent-dim);
  border-color: var(--accent);
  color: var(--accent-light);
}


.liq-effort {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

/* Text, not a graphic. The dial that was here read well at desk size
   and became a smudge at arm's length - eighteen pixels of circle
   cannot carry a five-way distinction on a phone, and a smudge sitting
   next to a numbered chip is worse than no mark at all.

   Right-aligned with a floor width so the numerals form a column that
   can be read down. Display face because these are figures, and the
   condensed face keeps "15m" inside the same width as "1d". */
/* Today's row is a flex line with align-items: flex-start, so the check
   button stays level with the first line of a title that wraps. The
   marks want the opposite - centred against the whole row, because they
   describe the task rather than its first line. .liq-row-body already
   carries flex: 1, so no auto margin is needed to push them right. */
.liq-row .liq-marks {
  align-self: center;
}

/* The pair. Adjacent and tight, because they are one answer read in two
   parts - what this is worth, against what it costs. */
.liq-marks {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  flex: 0 0 auto;
}

/* Cost is a chip too, and the same height as worth. Two chips side by
   side read as one control with two readings, which is what they are -
   a numeral floating next to a filled chip read as a stray label.

   Outlined rather than filled so worth still leads. Same shape, less
   weight. */
/* FIXED width, not min-width. A variable one let the divider wander
   down the column, because "15m" is wider than "1h" - and a ragged line
   inside a repeated object makes a list feel noisy without anyone being
   able to name why. 44px holds "365d". */
.liq-effort {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 30px;
  padding: 0 4px;
  border: 1px solid var(--border);
  border-radius: 7px;
  background: #2b2b36;
  font-family: var(--font-display, inherit);
  font-size: 16px;
  letter-spacing: 0.04em;
  line-height: 1;
  color: var(--text-primary);
  white-space: nowrap;
}

.liq-task.done .liq-effort,
.liq-task.is-done .liq-effort,
.liq-row-done .liq-effort {
  color: var(--text-dim);
  border-color: var(--border);
}

.liq-row-done .liq-weight {
  border-color: var(--border);
  background: transparent;
  color: var(--text-dim);
}

/* ==========================================================================
   Importance -- the weight chip

   Was five 4px dots, which is the quietest mark a row can carry, for
   the number the whole day gets sorted by. A solid chip with a numeral
   is the heaviest thing in the row now, which is the correct order:
   worth outranks cost.

   Colour climbs with the value. A five point scale in one colour has to
   be counted; one that changes colour does not. The 5 is the dragon
   orange on purpose - a 5 is what a dragon is made of, and the row
   should say so before you read the number.
   ========================================================================== */

/* 30px, not 24. The pair is meant to be read while scanning a phone at
   arm's length, and 24px with a 15px numeral is a size that works on a
   desk and disappears on a device. */
/* ==========================================================================
   The capsule -- one object, two readings

   Importance left, duration right, a single border around both and a
   divider between. They were two chips side by side and the complaint
   was never that they were small: it was that they could not be told
   apart. Two adjacent shapes have to be memorised. A position inside
   one object is learned in a glance and never unlearned.
   ========================================================================== */

.liq-capsule {
  display: inline-flex;
  align-items: stretch;
  flex: 0 0 auto;
  height: 30px;
  border: 1px solid var(--border-light, var(--border));
  border-radius: 8px;

  /* The segments square off their own corners against this. */
  overflow: hidden;
}

/* Inside the capsule the segments lose their own borders and radii -
   they are halves of one shape, not two shapes touching. */
.liq-capsule .liq-weight,
.liq-capsule .liq-effort {
  height: auto;
  border: 0;
  border-radius: 0;
}

.liq-capsule .liq-weight + .liq-effort,
.liq-capsule .liq-effort + .liq-weight {
  border-left: 1px solid var(--border-light, var(--border));
}

.liq-weight {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 30px;
  height: 30px;
  border: 1px solid var(--border);
  border-radius: 7px;
  font-family: var(--font-display, inherit);
  font-size: 17px;
  font-weight: 600;
  line-height: 1;
  color: var(--text-dim);
}

.liq-weight.w1,
.liq-weight.w2 {
  /* Deliberately flat. Most tasks are not important and a row of
     twenty should not look like twenty decisions. */
  border-color: var(--border);
  color: var(--text-dim);
}

.liq-weight.w3 {
  border-color: var(--accent-bord, var(--accent));
  background: var(--accent-dim, rgba(74, 158, 255, 0.18));
  color: var(--accent-light, var(--accent));
}

.liq-weight.w4 {
  border-color: var(--accent);
  background: rgba(74, 158, 255, 0.30);
  color: var(--text-primary);
}

.liq-weight.w5 {
  border-color: var(--dragon, var(--necessary));
  background: rgba(255, 140, 66, 0.28);
  color: var(--text-primary);
}

.liq-task.done .liq-weight,
.liq-task.is-done .liq-weight {
  border-color: var(--border);
  background: transparent;
  color: var(--text-dim);
}

/* Four across, two rows. Eight divides evenly and the labels are short
   now that each states its own value - "30 min" and "2 days" fit a
   quarter of a 360px phone at the 16px floor, where "Half day" did not
   fit a sixth. Three columns would leave two orphans on a third row. */
.liq-eff-pick {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 6px;
  margin-bottom: 4px;
}

.liq-eff-btn {
  min-height: var(--touch-target-touch, 44px);
  padding: 0 4px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg-raised);
  color: var(--text-secondary);
  font-family: inherit;
  font-size: var(--font-min-body, 16px);
  line-height: 1.2;
  cursor: pointer;
  white-space: nowrap;
}

.liq-eff-btn.on {
  background: var(--accent-dim, rgba(74, 158, 255, 0.18));
  border-color: var(--accent);
  color: var(--accent-light, var(--accent));
}

/* ==========================================================================
   Time log sheet -- "how long did it take", on completing a task
   (today.js 2.8.0)

   Deliberately not a reuse of .liq-mood-*. The geometry is the same
   today because both are bottom sheets on a phone, and that is a
   coincidence of shape, not a shared component. A selector named for
   moods governing the task-time sheet is exactly the kind of borrowing
   that makes a change to one silently break the other.
   ========================================================================== */

.liq-tlog-sheet {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  background: rgba(0, 0, 0, 0.55);
  padding: 16px;
}

.liq-tlog-panel {
  width: 100%;
  max-width: 420px;
  padding: 20px;
  background: var(--bg-elevated, var(--bg-surface));
  border: 1px solid var(--border);
  border-radius: 12px;

  /* Clear of the tab bar and the iOS home indicator. */
  margin-bottom: calc(var(--tabbar-h, 56px) + env(safe-area-inset-bottom, 0px));
}

.liq-tlog-ask {
  margin: 0 0 4px;
  font-size: var(--font-min-body, 16px);
  color: var(--text-primary);
}

/* The task name is context, not the question. Dimmer and one step
   down, and it truncates rather than wrapping to three lines and
   pushing the buttons off a short screen. */
.liq-tlog-task {
  margin: 0 0 14px;
  font-size: var(--font-min-secondary, 13px);
  color: var(--text-dim);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Four across, two rows. Eight durations is the whole ladder from a
   phone call to a full day, and four columns keeps "1h 30m" legible at
   the 16px floor on a 360px screen. */
.liq-tlog-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 6px;
  margin-bottom: 16px;
}

.liq-tlog-opt {
  min-height: var(--touch-target-touch, 44px);
  padding: 0 4px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg-raised);
  color: var(--text-secondary);
  font-family: inherit;
  font-size: var(--font-min-body, 16px);
  line-height: 1.2;
  cursor: pointer;
  white-space: nowrap;
}

.liq-tlog-opt.is-on {
  background: var(--accent-dim, rgba(74, 158, 255, 0.18));
  border-color: var(--accent);
  color: var(--accent-light, var(--accent));
}

.liq-tlog-acts {
  display: flex;
  gap: 8px;
}

.liq-tlog-btn {
  flex: 1 1 0;
  min-height: var(--touch-target-touch, 44px);
  padding: 0 12px;
  border-radius: var(--radius);
  border: 1px solid var(--border);
  background: transparent;
  color: var(--text-secondary);
  font-family: inherit;
  font-size: var(--font-min-body, 16px);
  font-weight: 600;
  cursor: pointer;
}

.liq-tlog-btn.is-primary {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--bg-base);
}

/* Skip carries no weight on purpose. A prompt you cannot dismiss on a
   bad day is a prompt that gets the whole ritual abandoned, so the way
   out is always visible and never styled as a failure. */
.liq-tlog-btn.is-quiet {
  flex: 0 0 auto;
  font-weight: 500;
  color: var(--text-dim);
}

/* ==========================================================================
   Wingman conversations (wingman.js 2.6.0)
   ========================================================================== */

.liq-wm-acts {
  display: flex;
  gap: 6px;
}

.liq-wm-sheet {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  background: rgba(0, 0, 0, 0.55);
  padding: 16px;
}

.liq-wm-panel {
  width: 100%;
  max-width: 460px;
  max-height: 72vh;
  padding: 16px;
  background: var(--bg-elevated, var(--bg-surface));
  border: 1px solid var(--border);
  border-radius: 12px;
  overflow-y: auto;

  /* clip, never hidden - hidden on one axis forces auto on the other,
     and this panel already scrolls vertically on purpose. */
  overflow-x: clip;
  margin-bottom: calc(var(--tabbar-h, 56px) + env(safe-area-inset-bottom, 0px));
}

.liq-wm-panel-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 12px;
  font-size: var(--font-min-body, 16px);
  color: var(--text-primary);
}

.liq-wm-group {
  margin: 14px 0 6px;
  font-size: 11px;
  letter-spacing: 0.09em;
  color: var(--text-dim);
}

.liq-wm-group:first-of-type {
  margin-top: 0;
}

/* Three tracks, three children, always. The two action buttons are
   never conditional - a row missing one would shift the other into its
   track. */
.liq-wm-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto;
  gap: 6px;
  align-items: center;
  padding: 4px 0;
  border-bottom: 1px solid var(--border);
}

.liq-wm-row.is-on .liq-wm-title {
  color: var(--accent-light, var(--accent));
}

.liq-wm-open {
  display: block;
  min-width: 0;
  min-height: var(--touch-target-touch, 44px);
  padding: 4px 0;
  border: none;
  background: transparent;
  text-align: left;
  font-family: inherit;
  cursor: pointer;
}

.liq-wm-title {
  display: block;
  font-size: var(--font-min-body, 16px);
  color: var(--text-primary);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.liq-wm-meta {
  display: block;
  margin-top: 2px;
  font-size: var(--font-min-secondary, 13px);
  color: var(--text-dim);
}

.liq-wm-icon {
  min-height: var(--touch-target-touch, 44px);
  padding: 0 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: transparent;
  color: var(--text-secondary);
  font-family: inherit;
  font-size: var(--font-min-secondary, 13px);
  cursor: pointer;
  white-space: nowrap;
}

.liq-wm-icon.is-danger {
  color: var(--noise, var(--text-dim));
  border-color: var(--border);
}

.liq-wm-note {
  margin: 12px 0 0;
  font-size: var(--font-min-secondary, 13px);
  color: var(--text-dim);
  line-height: 1.5;
}

/* ==========================================================================
   Drawer toggle -- optical centring

   Overriding a platform rule from product.css rather than editing
   shell.css. shell.css is the shared bundle and every IQ product has a
   copy; a fix made there diverges this product's copy from the baseline
   and gets silently reverted the next time the bundle is updated.
   Product-level overrides are what this file is for.

   The glyph is &##9776; - a text character, flex-centred in a 40px box.
   Flex centres the LINE BOX, not the ink, and where the ink falls
   inside that line box is a property of the font's ascent and descent.
   iOS resolves the fallback differently than desktop does, so the same
   markup sits a pixel low on a phone and correct on a laptop. Nothing
   about the CSS was wrong; it was measuring the wrong thing.

   line-height: 1 collapses the line box to the glyph itself, which
   removes most of the variance. The 2px bottom padding shifts the
   centred content up 1px inside an unchanged 40px border box - the
   button does not move or resize, only the ink inside it.
   ========================================================================== */

.btn-menu-toggle {
  line-height: 1;
  padding: 0 0 2px;
}

/* ==========================================================================
   Shell scrolling -- the min-height: auto trap

   .iq-content and .iq-sidebar are grid items inside #iq-root, which is
   height: 100dvh and overflow: hidden. Both declare overflow-y: auto
   and neither could scroll.

   A grid item's default min-height is AUTO, not zero, which means it
   refuses to be smaller than its own content. So a tall conversation
   made .iq-content grow past its 1fr track rather than scroll inside
   it: the box ended up exactly as tall as its content, so there was
   never any overflow for overflow-y to act on, and #iq-root's
   overflow: hidden then clipped everything past the viewport. The page
   looked frozen with its bottom cut off, which is precisely what it
   was.

   min-height: 0 lets the track win the argument. The item takes the
   1fr height, its content overflows it, and overflow-y does its job.

   Wingman surfaced it because a conversation is the tallest thing this
   app renders. Every other screen has the same bug and has simply not
   been long enough to trip it yet.

   Overridden here rather than edited into shell.css so this product's
   copy of the shared bundle stays at baseline. It is a real platform
   defect and every IQ product has it - the durable fix is one line in
   the bundle, not four product overrides.
   ========================================================================== */

.iq-content,
.iq-sidebar {
  min-height: 0;
}

/* ==========================================================================
   Wingman -- a column that fills the viewport (wingman.js 2.7.0)

   Three rows. The header and the composer are ROWS, not sticky things
   floating inside a scrolling page, and the message list is the only
   element with an overflow. It is bounded above by the header and below
   by the composer, so a message has nowhere to go behind either one.
   Overlap is impossible by construction instead of being painted over.

   What this replaces: position: sticky inside .iq-content plus negative
   margins trying to cover that container's padding. Negative margin
   pulls an element out of flow, which was the dead gap under the
   composer, and a sticky element never contains anything, so messages
   rendered above the header and below the composer anyway. Three
   rounds of adjusting the numbers could not fix a wrong shape.
   ========================================================================== */

/* The page stops scrolling on this screen. :has is already relied on in
   shell.css for the login layout, so the support floor is unchanged. */
.iq-content:has(.liq-wm-screen) {
  overflow: hidden;
  padding: 0;
}

.liq-wm-screen {
  display: flex;
  flex-direction: column;
  height: 100%;

  /* The same min-height: 0 that broke .iq-content yesterday. A flex
     child will not shrink below its content unless told to, and without
     it the message list pushes the composer off the bottom. */
  min-height: 0;

  /* .iq-content's own bottom padding cleared the tab bar; that padding
     is gone now, so the column takes the job. */
  padding-bottom: calc(var(--tabbar-h, 0px) + env(safe-area-inset-bottom, 0px));
}

/* Two inherited rules had to go.

   .liq-section-head carries margin: 22px 2px 8px, which is right for a
   heading in the middle of a scrolling page and wrong for row one of a
   fixed column - it stacked on top of this rule's own padding and put
   about thirty pixels of nothing under the topbar.

   It also carries align-items: baseline. That aligns a 36px button to
   an 11px label's baseline, which drops the buttons and leaves the gap
   ABOVE them. Baseline is right when a row is all text; centre is right
   when a row mixes text with controls. */
.liq-wm-head {
  flex: 0 0 auto;
  align-items: center;
  margin: 0;
  padding: 8px 16px;
  border-bottom: 1px solid var(--border);
  background: var(--bg-base);
}

/* Opens at two rows and grows to 140px as you type. Three rows of empty
   box was reserving room for text that is usually one line, on the
   screen with the least room to spare. */
.liq-wm-screen .liq-composer-in {
  min-height: 0;
}

.liq-wm-scroll {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overflow-x: clip;
  padding: 12px 16px;

  /* Momentum scrolling, and it keeps a flick inside this box instead of
     handing it to the page behind. */
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
}

/* Row three. Overrides the sticky positioning the base rule still
   carries for any other screen that uses a composer. */
.liq-wm-screen .liq-composer {
  position: static;
  flex: 0 0 auto;
  margin: 0;
  padding: 10px 16px 12px;
  border-top: 1px solid var(--border);
  background: var(--bg-base);
}

/* The sheet is a sibling of the column, not a row in it - it covers the
   header, so it cannot live inside the thing it covers. */
.liq-wm-sheet {
  align-items: flex-end;
}

@media (max-width: 480px) {

  .liq-wm-head          { padding: 8px 12px; }
  .liq-wm-scroll        { padding: 10px 12px; }
  .liq-wm-screen .liq-composer { padding: 10px 12px 12px; }
}

/* ==========================================================================
   The morning read, offered (wingman.js 2.8.0)

   A chip in the empty state instead of the read itself. It only exists
   when there is a check-in to read, and it disappears the moment the
   conversation has a message - it belongs to the opening, and after the
   opening there is nothing left for it to open.
   ========================================================================== */

.liq-opener-chip-wrap {
  align-self: flex-start;
  max-width: 100%;
}

/* Dashed, and it is not decoration. A solid pill in the accent reads as
   the primary action on an otherwise empty screen, which is the exact
   pressure this change exists to remove. Dashed says available. */
.liq-opener-chip {
  display: inline-flex;
  align-items: center;
  min-height: var(--touch-target-touch, 44px);
  padding: 0 14px;
  border: 1px dashed var(--accent-bord, var(--border-light));
  border-radius: 999px;
  background: transparent;
  color: var(--accent-light, var(--accent));
  font-family: inherit;
  font-size: var(--font-min-secondary, 13px);
  cursor: pointer;
  text-align: left;
}

/* The timestamp sits outside the chip, quieter than the label. It is
   the deciding information and it should not compete with the thing you
   tap - you read the time, then decide about the chip. */
.liq-opener-when {
  margin: 6px 0 0 4px;
  font-size: var(--font-min-secondary, 13px);
  color: var(--text-dim);
}

.liq-opener {
  align-self: flex-start;
  max-width: 86%;
}

.liq-opener .liq-msg {
  max-width: 100%;
}

/* Overrides the note's old standalone margins - it is inside .liq-opener
   now and the gap belongs to the container. */
.liq-opener .liq-opener-note {
  margin: 6px 0 0 4px;
}

/* Text, not a button. Hide is an undo, and an undo styled as a control
   equal to the thing it undoes makes the original act look weightier
   than it is. */
.liq-opener-hide {
  padding: 0;
  border: none;
  background: none;
  color: var(--accent-light, var(--accent));
  font-family: inherit;
  font-size: inherit;
  text-decoration: underline;
  cursor: pointer;
}

/* ==========================================================================
   Delete a log entry (reality.js 1.3.0)

   Full width so it is not mistaken for a secondary action beside Save,
   and quiet so it is not mistaken for the primary one. Text on a
   transparent ground in the noise colour: findable when looked for,
   not competing when not.

   A filled red button here would be the loudest thing on the form, and
   the loudest thing on a form should never be the irreversible one.
   ========================================================================== */

.liq-log-del {
  display: block;
  width: 100%;
  min-height: var(--touch-target-touch, 44px);
  margin-top: 8px;
  padding: 0 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: transparent;
  color: var(--noise, var(--text-dim));
  font-family: inherit;
  font-size: var(--font-min-body, 16px);
  cursor: pointer;
}

/* ==========================================================================
   Mood row on Today (today.js 2.11.0)

   Five dots and whatever has been logged so far. The sheet's scale uses
   44px tappable blocks because it is the only thing on that screen;
   here the row shares Today with everything else, so the dots are
   circles on a 44px tap target rather than 44px slabs.

   Colours match .liq-mood-dot exactly. Two scales for one measurement
   that disagreed on colour would make the row and the sheet look like
   different features.
   ========================================================================== */

.liq-moodrow {
  padding: 12px 14px;
}

.liq-moodrow-top {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 10px;
}

.liq-moodrow-ask {
  font-size: var(--font-min-body, 16px);
  color: var(--text-primary);
}

.liq-moodrow-log {
  display: flex;
  align-items: center;
  gap: 4px;
  min-width: 0;
}

/* The readings so far, in order. Not a count: "3 logged" is a score and
   invites logging for the number. The levels and the last time are the
   information. */
.liq-moodrow-pip {
  display: block;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--text-dim);
}

.liq-moodrow-pip.vn2 { background: var(--noise); }
.liq-moodrow-pip.vn1 { background: var(--necessary); }
.liq-moodrow-pip.vp0 { background: var(--text-dim); }
.liq-moodrow-pip.vp1 { background: var(--accent); }
.liq-moodrow-pip.vp2 { background: var(--signal); }

.liq-moodrow-last {
  margin-left: 4px;
  font-size: var(--font-min-secondary, 13px);
  color: var(--text-dim);
  white-space: nowrap;
}

/* Five children, five tracks, at every width. */
.liq-moodrow-scale {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 6px;
}

/* The visible dot is smaller than the target it sits in. A 7px circle
   is the right size to read as a scale and far too small to hit with a
   thumb, so the button keeps the full 44px and draws a circle in the
   middle of it. */
.liq-moodrow-dot {
  position: relative;
  min-height: var(--touch-target-touch, 44px);
  padding: 0;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg-raised);
  cursor: pointer;
}

.liq-moodrow-dot::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: 12px;
  height: 12px;
  margin: -6px 0 0 -6px;
  border-radius: 50%;
  background: currentColor;
}

.liq-moodrow-dot.vn2 { color: var(--noise); }
.liq-moodrow-dot.vn1 { color: var(--necessary); }
.liq-moodrow-dot.vp0 { color: var(--text-dim); }
.liq-moodrow-dot.vp1 { color: var(--accent); }
.liq-moodrow-dot.vp2 { color: var(--signal); }

/* ==========================================================================
   IQ.dt inside a labelled row -- the grid-as-flex-item trap

   .liq-when-row is a flex row: a label, then IQ.dt.timeSelect. That
   returns a <span class="iq-dt"> which is display: grid.

   A grid container used as a flex item still obeys flex sizing, and the
   default is flex: 0 1 auto - it sizes to its CONTENT and never claims
   the space beside the label. Its three fr tracks then divided a box
   that had never been given any width, which is why the selects stayed
   skinny no matter what the padding said. The caret was not overlapping
   because of padding; it was overlapping because the whole control was
   about half the width it should have been.

   flex: 1 1 auto makes it take the row. min-width: 0 lets it be smaller
   than its content so it can shrink on a 360px screen instead of
   overflowing.

   The margin-bottom is for a stacked form field, not a row that already
   has its own spacing.
   ========================================================================== */

.liq-when-row .iq-dt {
  flex: 1 1 auto;
  min-width: 0;
  margin-bottom: 0;
}

/* The day count, rung 6 only. Present when it matters and absent when
   it does not - a field that greys out teaches you to ignore the space
   it occupies, and then you miss it on the day it appears. */
.liq-eff-days {
  margin-bottom: 4px;
}

.liq-eff-days.is-hidden {
  display: none;
}

/* ==========================================================================
   Subtask lines on Today (today.js 2.14.0)

   Read only. Tasks owns editing them - a second place to tick the same
   row is a second place for the two to disagree.

   Indented to the title's left edge, not the row's, so they read as
   belonging to the task rather than as more tasks.
   ========================================================================== */

.liq-sublines {
  margin-top: 6px;
  padding-left: 2px;
  border-left: 2px solid var(--border);
}

.liq-subline {
  display: flex;
  align-items: baseline;
  gap: 6px;
  padding: 2px 0 2px 8px;
  font-size: var(--font-min-secondary, 13px);
  color: var(--text-secondary);
  line-height: 1.35;
}

.liq-subline-tick {
  flex: 0 0 10px;
  color: var(--text-dim);
}

.liq-subline.is-done {
  color: var(--text-dim);
  text-decoration: line-through;
}

.liq-subline.is-done .liq-subline-tick {
  color: var(--signal);
  text-decoration: none;
}

.liq-subline.is-more {
  color: var(--text-dim);
  padding-left: 24px;
}

/* ==========================================================================
   Working state on a primary button (checkin.js 1.4.0)

   Opening and closing the day both take a moment, and nothing on screen
   changed when the button was pressed. _busy already swallowed a second
   press, which made it worse rather than better: the button ignored you
   and did not say so, and the reasonable reading was that the first
   press had missed.
   ========================================================================== */

.btn.is-working {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 9px;

  /* Not dimmed. A disabled-looking primary button on a screen that is
     mid-request reads as "this failed", which is the opposite of what
     is happening. */
  opacity: 1;
  cursor: default;
}

.liq-spin {
  flex: 0 0 auto;
  width: 15px;
  height: 15px;
  border: 2px solid rgba(0, 0, 0, 0.25);

  /* currentColor, so it works on any button colour without a second
     rule per variant. */
  border-top-color: currentColor;
  border-radius: 50%;
  animation: liq-spin 0.7s linear infinite;
}

@keyframes liq-spin {
  to { transform: rotate(360deg); }
}

/* Reduced motion still needs to say something is happening, so the ring
   pulses instead of turning. Removing the indicator entirely would put
   the person back where they started. */
@media (prefers-reduced-motion: reduce) {

  .liq-spin {
    animation: liq-pulse 1.2s ease-in-out infinite;
  }

  @keyframes liq-pulse {
    0%, 100% { opacity: 0.35; }
    50%      { opacity: 1; }
  }
}