/* The patient web app in a browser window: the design (ui/web.css, generated)
   draws it inside the simulator's frame; here it fills the window. */
html, body { margin: 0; min-height: 100%; background: var(--bg-page, #ebeef0); }
.web { width: 100%; min-height: 100dvh; }
.web:has(> .web-root) { height: 100dvh; }

/* The white panel (.lmain) is a `web` container too, so the frame's own breakpoints ask the window's
   width by a name only the outer element has. */
.web:has(> .web-root) { container-name: web webapp; }

/* As the simulator's host page: the design's display rules mustn't beat the hidden attribute. */
[hidden] { display: none !important; }

/* Waiting for the next page shows in the clicked control (ui/web_wait.js), or for a text link and a wait nothing
   clicked owns in our own bar (.nw-bar), which also covers the drawer's loads; Turbo's bar only sees page visits. */
.turbo-progress-bar { display: none; }
/* A data tile (data-wait="overlay") keeps the patient's numbers: it holds its hover and pressed look from the
   click (aria-busy), and after 300 ms a wash of its own held surface, the web-busy card's at tile scale, takes the
   spinner over them. */
:where(.web) :is(.rp-stats, .rp-m)[aria-busy="true"] { background-color: var(--tint); }
:where(.web) .mbtn[aria-busy="true"] { background-color: var(--hover); }
/* Outranks the link resets below (.web a's underline, .web a:is(.rp-m, .mbtn)'s none) and covers the tile. */
.web a[data-wait="overlay"][aria-busy="true"] { background-image: linear-gradient(var(--press), var(--press)); background-size: 100% 100%; }
.nb-wash { position: absolute; inset: 0; border-radius: inherit; pointer-events: none;
  background: var(--nb-wash, color-mix(in srgb, var(--bg-surface) 60%, transparent));
  animation: fadeIn var(--dur-base) var(--ease) both; }
/* A text-only nav item (data-wait="end" on the nav) keeps its label and spins at its end, taking the selected
   look from the click as the kiosk's Operator menu does. The item keeps its size: the row's pills have no
   room for the spinner in their end padding, so the label moves over into the start padding while it waits. */
.subnav a { transition: padding var(--dur-fast) var(--ease); }
.subnav a[aria-busy="true"] { color: var(--text); background: var(--bg-surface); box-shadow: var(--ring-soft), var(--lift); }
.subnav:has(a[aria-busy="true"]) a[aria-current="page"]:not([aria-busy="true"]) { color: var(--text-2); background: none; box-shadow: none; }
@container web (max-width: 1023.98px) {
  .subnav a[aria-busy="true"]:has(.nb-end) { padding-inline: 4px 28px; }
  .subnav .nbx.nb-end { inset-inline-end: 6px; }
}
@container web (min-width: 1024px) {
  .subnav a[aria-busy="true"] { background: var(--selected); box-shadow: none; }
}
/* A switch whose options are page visits (the results tabs): ui/web_wait.js slides the switch's own pill, in the
   selected option's look, to the tapped option while the next page is on its way, then hands back to the option's
   (.seg-set: without fading it in). The tabs are sized to their labels, so it is placed from script. */
.tabs { position: relative; isolation: isolate; }
.tabs.seg-go::before { content: ""; position: absolute; z-index: -1; top: 4px; bottom: 4px; left: var(--seg-x); width: var(--seg-w);
  border-radius: 9999px; background: var(--bg-surface); box-shadow: var(--ring-soft), var(--lift); pointer-events: none;
  transition: left var(--dur-base) var(--ease-move), width var(--dur-base) var(--ease-move); }
/* A text link's wait, or one nothing clicked owns (ui/web_wait.js): a bar along the top, over the drawer and the
   toast, in the kiosk's page disc's ring colour and with no track. It eases most of the way while it waits, then
   runs to the end and fades. */
.nw-bar { position: absolute; top: 0; left: 0; right: 0; z-index: 91; height: 3px; background: var(--brand-primary); pointer-events: none;
  transform: scaleX(0); transform-origin: left; }
.nw-bar:dir(rtl) { transform-origin: right; }
@media (prefers-reduced-motion: reduce) {
  .nb-after, .nb-after .nbx { transition: none; }
  .nw-bar, .nw-bar.on { transform: none; transition: none; }
  .nb-wash { animation: none; }
  .subnav a { transition: none; }
}

/* A short page puts the footer at the panel's foot, not under the last card; a long one pushes it down as before
   (Rodger, 3 Nov). The page and footer keep their max-width and auto margins, so they need a width to centre. */
.lmain .vscroll { display: flex; flex-direction: column; }
.lmain .vscroll > .page { flex: 1 0 auto; width: 100%; }
.lmain .vscroll > .apphdr, .lmain .vscroll > .appfoot { flex: none; width: 100%; }

/* The simulator picks the rail or the top bar in script (railOn, 1024 px and up); here the width does. */
@container webapp (max-width: 1023.98px) {
  .appshell { display: block; }
  .appshell .lrail { display: none; }
  /* Without the rail there's no white panel: the page as the simulator's AppPage draws it. */
  .appshell .lmain { position: absolute; inset: 0; margin: 0; background: none; border-radius: 0; box-shadow: none; }
  .appshell .lmain .page { padding-top: 0; max-width: 1120px; }
  .appshell .lmain .appfoot { max-width: 1120px; }
  .appshell .lmain .card { background: var(--bg-surface); box-shadow: none; }
  .appshell .lmain .back { display: inline-flex; }
}
@container webapp (min-width: 1024px) {
  .appshell .apphdr { display: none; }
}
.lrail .logo.min, .lrail.min .logo.full { display: none; }
.lrail.min .logo.min { display: inline-flex; }

/* The menu's tap-away area, and its items as links and a sign-out form. From the rail the menu
   keeps the account items; the rail is the navigation. */
.menu-scrim { position: absolute; inset: 0; }
.menu form, .srow .a form, .idle-acts form { display: contents; }
.menu.from-rail .who, .menu.from-rail .mi.nav { display: none; }

/* The design draws these as buttons; here they're links, which .web a would colour. */
.web a.lr-i, .web a.mi { color: var(--text); }
.web a.lr-i { font-weight: 600; }
.web a.mi { font-weight: 500; }
.subnav a { position: relative; display: inline-flex; align-items: center; height: 40px; padding: 0 16px; font-size: 15px; font-weight: 600; color: var(--text-2); white-space: nowrap; border-radius: 9999px; flex: none; }
.subnav a[aria-current="page"] { color: var(--text); background: var(--bg-surface); box-shadow: var(--ring-soft), var(--lift); }
@container web (min-width: 1024px) {
  .subnav a { height: 44px; border-radius: 12px; }
  .subnav a[aria-current="page"] { background: var(--selected); box-shadow: none; }
}
:where(.web.hov) .subnav a:hover { color: var(--text); }

/* A dialog whose main button leads the markup, so Enter in its field submits that one. */
.mini .acts.submit-first > .alt { order: -1; }
.mini .acts.submit-first > .btn.fill { order: 1; }
/* Stay logged in leads the idle warning's markup, as the button session-timeout focuses; Log out shows first. */
.idle-acts > form .btn { order: -1; }

/* The design marks a chosen option and a ticked box with classes (.opt.sel, .check.on); here they're real
   form inputs, so the same looks follow the input. */
.opt { position: relative; cursor: pointer; }
/* The radio fills the chip, so a tap lands on a form control: iOS WebKit holds a <label>'s click about 32 ms
   for hover emulation, and the chip showed white between the press tint and the selected colour. */
.opt input { position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; opacity: 0; appearance: none; cursor: pointer; border-radius: inherit; }
.web .opt:has(input:checked), .web .opt:has(input:checked):hover { background: var(--selected); box-shadow: var(--lift-selected); transform: none; }
/* As the design's .opt.sel: the chosen colour lands at once. Faded in, it showed the white surface for 150ms
   between the press tint (a background-image, which can't transition) and the selected colour. */
.web .opt:has(input:checked) { transition: box-shadow var(--dur-base) var(--ease), transform var(--dur-base) var(--ease); }
.opt:has(input:focus-visible) { outline: 2px solid var(--border-action); outline-offset: 2px; }
.check:has(input:checked) .box { background: var(--brand-primary); border-color: var(--brand-primary); }
.check:not(:has(input:checked)) .box .ic { visibility: hidden; }

/* A long email address in a line of copy wraps rather than running past the card. */
.cs { overflow-wrap: anywhere; }

/* Your results: the tabs and filters are links (a page visit, so the top
   bar's PDF and Print follow the tab too). */
a.tab { display: inline-flex; align-items: center; }
a.fchip { text-decoration: none; }
/* The kit marks its toggle chips with aria-pressed; these are links, so the
   current filter is aria-current, styled the same. */
.web .fchip[aria-current="true"], .web .fchip[aria-current="true"]:hover:not([disabled]) { background: var(--selected); box-shadow: var(--lift-selected); transform: none; }

/* Your measurements: the rail shows them from 1024 px; below that, the
   results page's summary card does (the simulator picks one in script). */
@container webapp (min-width: 1024px) { .appshell:not(:has(.lrail.min)) .dash .card.sum { display: none; } }
/* A collapsed rail has no room for them: the summary card shows instead. */
.lrail.min .rp-block { display: none; }

/* My health profile: the kit's yes/no and unit toggles are buttons; here they
   are radios, so the form posts without script. The labels take the buttons'
   look and the checked one moves the kit's pill. */
:is(.yn, .unitseg) > label { position: relative; display: grid; place-items: center; cursor: pointer; border-radius: 9999px; font-weight: 600; color: var(--text-2); transition: color var(--dur-fast) var(--ease); }
.yn > label { height: 34px; font-size: 14px; padding: 0 14px; }
.unitseg > label { height: 28px; font-size: 13px; padding: 0 10px; }
:is(.yn, .unitseg) > label > input { position: absolute; inset: 0; opacity: 0; margin: 0; cursor: pointer; }
:is(.yn, .unitseg) > label:has(input:checked) { color: var(--text); }
:is(.yn, .unitseg) > label:has(input:focus-visible) { outline: 2px solid var(--border-action); outline-offset: 1px; }
:is(.yn, .unitseg):has(> label:nth-child(3)) { --n: 3; }
:is(.yn, .unitseg):has(> label:nth-child(1) input:checked) { --i: 0; --on: 1; }
:is(.yn, .unitseg):has(> label:nth-child(2) input:checked) { --i: 1; --on: 1; }
:is(.yn, .unitseg):has(> label:nth-child(3) input:checked) { --i: 2; --on: 1; }
/* Only the chosen unit's fields show; cm or kg alone spans both columns. */
.hp-row[data-unit="in"] > [data-units="cm"], .hp-row[data-unit="cm"] > [data-units="in"],
.hp-row[data-unit="lbs"] > [data-units="kg"], .hp-row[data-unit="kg"] > [data-units="lbs"] { display: none; }
.hp-row[data-unit="cm"] > [data-units="cm"], .hp-row[data-unit="kg"] > [data-units="kg"], .hp-row.one > [data-units="lbs"] { grid-column: 1 / 3; }

/* PDF and Print sit in the heading beside the rail, and in the top bar
   where there's no rail (the simulator picks one in script). */
@container webapp (max-width: 1023.98px) { .dash-head .pacts { display: none; } }

/* Your results on paper (Web::Report): Print shows it in place of the page,
   and the PDF renders it alone. On screen it isn't shown: the simulator's
   report preview is the simulator's own. A sheet is the region's paper
   (its @page size is ui/paper_a4 or ui/paper_letter, linked by region),
   a touch under its full height so rounding never spills a blank page. */
.print-report { display: none; }
.report-pdf { margin: 0; background: #ffffff; font-family: var(--font-ui); font-size: 16px; line-height: 1.5; -webkit-font-smoothing: antialiased; }
.report-pdf .print-report { display: block; }
/* Browsers print without backgrounds by default, which drops the band segments, the pills' fill and the status dots;
   the PDF gets them from FerrumPdf's print_background. */
.print-report { -webkit-print-color-adjust: exact; print-color-adjust: exact; }
.print-report .paper { position: relative; box-shadow: none; border-radius: 0; break-after: page; overflow: hidden; }
.print-report .paper:last-child { break-after: auto; }
.print-report .paper.a4 { width: 794px; height: 1122px; }
.print-report .paper.letter { width: 816px; height: 1055px; }
@media print {
  html, body, .web { background: #ffffff !important; }
  .web .lrail, .web .apphdr, .web .appfoot, .web .dash > :not(.print-report), .web-root > :not(.appshell) { display: none !important; }
  /* Every container, the outer .web too (100dvh, overflow hidden), opens
     up so the sheets after the first aren't cut off. */
  .web, .web-root, .web .appshell, .web .lmain, .web .vscroll, .web .page, .web .dash { display: block; position: static; overflow: visible; height: auto; min-height: 0; margin: 0; padding: 0; border: 0; box-shadow: none; background: none; }
  .print-report { display: block; }
}

/* Result rows, the heart card, the next-risk card and the menu tiles are links here, where the simulator makes them
   buttons, so the kit's link rule (.web a: semibold, link colour, hover underline, 1px bottom padding) reached their
   text and their padding: every sub-line and range note came out semibold (Rodger, 28 Oct). Undone, with each one's
   own bottom padding restated where .web a outranks it (the heart card's own .hc.hc-combo rule already wins). */
.web a:is(.rrow, .hc, .nrisk, .rp-m, .mbtn) { font-weight: 400; color: inherit; background-image: none; }
.web a.rrow { padding-bottom: 16px; }
.web a.nrisk { padding-bottom: 20px; }
.web a.rp-m { padding-bottom: 8px; }
.web a.mbtn { padding-bottom: 6px; }
@container web (min-width: 768px) { .web a.rrow { padding-bottom: 14px; } }
@container web (min-width: 1024px) { .web a.rrow { padding-bottom: 16px; } }
/* The reset above outranks the heart card's own press tint (.hc:active): restore it, covering the card (the link
   rule's background-size would hide it). */
.web a.hc:active { background-image: linear-gradient(var(--press), var(--press)); background-size: 100% 100%; }
/* A dialog's next step (web/dialog_controller "stay") replaces it in place: no second slide or fade in. */
.ov.stay .dlg, .ov.stay .scrim { animation: none; }

/* Terms of use and Privacy policy in the web app's dialog: the public site's HTML (headings, numbered sections), set
   in the dialog's type rather than the kit's spaced sections. */
.legal .lg-body.legal-html { display: block; }
.legal-html h6 { margin: 20px 0 6px; font-size: 16px; font-weight: 600; color: var(--text); }
.legal-html p, .legal-html li { margin: 0 0 10px; font-size: 15px; line-height: 1.5; color: var(--text-2); }
.legal-html ol, .legal-html ul { margin: 0 0 10px; padding-left: 20px; }
.legal-html a { word-break: break-word; }
/* The policy stores its email and phone reversed (against scrapers); the public site's and the kiosk's styles turn
   them back, and this dialog must too. */
.legal-html .pubeml { unicode-bidi: bidi-override; direction: rtl; }

/* CONTOUR® readings' drawer (HEA-223): a chart per meal, and the summary's periods in the readings list's rhythm. */
.rx-sub { margin: 16px 0 4px; font-size: 16px; font-weight: 600; color: var(--text); }
.rx-sum { display: flex; flex-direction: column; margin-bottom: 8px; }
.rx-sum li { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: center; gap: 8px 24px; padding: 12px 0; border-top: 1px solid var(--border-subtle); }
.rx-sum li:last-child { border-bottom: 1px solid var(--border-subtle); }
.rx-sum .p { display: flex; flex-direction: column; gap: 2px; font-size: 16px; color: var(--text); }
.rx-sum .p .c2 { font-size: 14px; }
.rx-sum .av { display: flex; gap: 20px; font-size: 14px; color: var(--text-2); }
.rx-sum .av b { font-family: var(--font-mono); font-size: 16px; font-weight: 500; color: var(--text); }

/* Fax: the neutral score (QDiabetes) in black like every other result. The kit's .paper .pz i.on.neu comes after
   its fax rule at the same weight, so it kept its navy tint. */
.paper.fax .pz i.on.neu { background: #fff; color: #000; box-shadow: inset 0 0 0 2.5px #000; }

/* The range zones' hover tip (ui/controllers/web/zone_tip): the kit's .ztip is display: flex, so hidden needs saying. */
.ztip[hidden] { display: none; }

/* A field label with an info tip after it (simulator Signup: Sex, then InfoTip). */
.t-label.fl-tip { display: inline-flex; align-items: center; gap: 4px; }

/* Only text links underline on hover (Rodger, 30 Oct): the kit draws the grow-in underline on every `.web a`.
   An anchor that's a component (a class other than .lnk: rows, cards, chips, tabs, menu and rail items, back
   links), any anchor in navigation or the app header (Settings' sub-navigation, the logo), and one that holds an
   icon or the logo draws none. Plain anchors in running text, .lnk and the footers' Terms and Privacy keep it.
   Only the line: components keep their own padding, and the extras sit in :where() so this rule has the kit's
   `.web a` weight and their pressed state (also a background-image) still wins. That gradient fills them: at the
   line's hover size it drew a faint underline along a pressed tab's or chip's foot. */
.web a:where([class]:not(.lnk), nav a, .apphdr a, :has(> svg, > .ic, > .logo)) { background-image: none; background-size: 100% 100%; }

/* Show / Hide in a password field: both words stacked in one grid cell, so the button is as wide as the longer word in
   any language and the shown one is centred; swapping them never moves the button's edge. */
.inp-wrap .suffix .btn:has(> .tg-l) { display: inline-grid; place-items: center; }
.inp-wrap .suffix .btn > .tg-l { grid-area: 1 / 1; }
.inp-wrap .suffix .btn > [data-state="hide"], .inp-wrap .suffix .btn.on > [data-state="show"] { visibility: hidden; }
.inp-wrap .suffix .btn.on > [data-state="hide"] { visibility: visible; }

/* No scrollbars on a touch screen, from the first paint: the kit's .web.touch rule waits for web_theme_controller to
   add the class, so the panel lost its 12px bar after load and everything in it shifted. The query is that controller's
   test for .touch. */
@media not all and (hover: hover), not all and (pointer: fine) {
  .web, .web * { scrollbar-width: none; }
  .web ::-webkit-scrollbar { display: none; }
}

/* Google's reCAPTCHA notice under Create account (DESIGN.md, HEA-253); the simulator has no rule for it.
   Google lets the corner badge go only while the notice is on the page. */
.captcha { margin: 0; font-size: 12px; line-height: 1.45; color: var(--text-3); text-align: center; }
.captcha a { color: inherit; text-decoration: underline; }
:root:has(.captcha) .grecaptcha-badge { visibility: hidden; }
/* The device keyboard (ui/keyboard_view, Rodger, 3 Nov). On iPhone Safari the page stays full height under it, so the
   open sheet takes only the visible part (data-kbd). With little height left and a field focused (.kbd-short), the
   title keeps one line and the intro goes, so the fields have the room; Cancel and Save stay. */
.ov[data-kbd] { top: var(--vvt, 0px); bottom: auto; height: var(--vvh); }
.ov.kbd-short .dr-hd { gap: 0; padding-top: 12px; padding-bottom: 8px; }
.ov.kbd-short .dr-ttl .t-title { font-size: 20px; line-height: 1.25; letter-spacing: -0.3px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ov.kbd-short .dr-ttl .tx > p { display: none; }
.ov.kbd-short .dr-ttl .dr-x { margin-top: 0; }
.ov.kbd-short .dr-body { padding-top: 16px; }
.ov.kbd-short .box.chg { gap: 10px; }
.ov.kbd-short .box.chg > .chg-k, .ov.kbd-short .box.chg > p.t-body { display: none; }
.ov.kbd-short .box.chg > .t-h2 { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* The Health profile's section labels go too (HEA-280, signed off 4 Nov). */
.ov.kbd-short .hp-head { display: none; }

/* The Type 2 diabetes risk card (Rodger, 3 Nov 2026): a bigger number, its line box trimmed to the digits, so the
   two-line sentence beside it is centred on the figures and sits inside their height instead of hanging below. */
.nrisk .big span { font-size: 15px; line-height: 1.3; }
/* With the number's box trimmed, the title, number and QDiabetes line need more room between them. */
.nrisk .tx { gap: 12px; }
/* The heart age labels, moved back inside the track when a dot near an end would push one off the card
   (web-age-labels). translate composes with each label's own transform. */
.hac-l span { translate: var(--shift, 0px) 0; }

/* The kiosk rail's Log out is a button_to (a form and a button), styled as the rail's links are: the kit's rail-foot
   weight (500) and, with .out, the account menu's error-tone icon. */
.lr-foot form { display: contents; }
.lr-foot button.lr-i { width: 100%; background: none; border: 0; font-family: inherit; text-align: start; cursor: pointer; }
/* 24px up from the rail's foot puts the foot item's text (Log out on a kiosk, Find a location elsewhere) level with
   the footer's line beside it (Rodger, 3 Nov 2026; Find a location 5 Nov). */
.lrail .lr-foot { margin-bottom: 24px; }
/* One weight above the kit's rail foot and in their navy, as Results and Health profile are (Rodger, 3 Nov 2026). */
.lr-foot button.lr-i.out { font-weight: 600; color: var(--text); }
/* My health profile's section labels; About you carries its info tip beside it. */
.hp-head { display: flex; align-items: center; gap: 6px; }
/* My health profile: About you sits closer under the title and lede (Rodger, 3 Nov 2026). The drawer's 28px body
   padding on top of the header's 12px left a gap larger than the space between sections. */
.dr-body:has(> .hp) { padding-top: 12px; }

/* A link in a settings row's value (the Help page's support email) sizes to its text: the value is a flex column,
   which would stretch it, and its hover underline with it, across the whole row (Rodger, 5 Nov 2026). */
.srow .v > a { align-self: flex-start; }

/* Your results' Follow-up filter switches in the browser (web/results_filter_controller.js): the server renders every
   result, marking the flagged ones data-fu, and the .dash's data-filter hides the rest. A group with nothing flagged
   goes, and so does the divider above its first flagged row (Rodger, 10 Nov 2026). */
.dash:not([data-filter="follow_up"]) > .rf-none { display: none; }
.dash[data-filter="follow_up"] > .grp :is(.rrow, .hcrow, .nrisk, .grp-note):not([data-fu]) { display: none; }
.dash[data-filter="follow_up"] > .grp:not(.rf-none):not(:has([data-fu])) { display: none; }
.dash[data-filter="follow_up"] > .grp .rrow[data-fu]:not(.rrow[data-fu] ~ .rrow) { margin-top: 0; }
.dash[data-filter="follow_up"] > .grp .rrow[data-fu]:not(.rrow[data-fu] ~ .rrow)::before { content: none; }
