/* Everything the published site and the local editor both use.
 *
 * One file, because the alternative was three: the design tokens lived in
 * site.css, the per client overrides in a generated client.css, and the marker
 * in markers.css. The editor loaded some of them and not others, which is how it
 * ended up wearing one client's accent colour while auditing another.
 *
 * The rule for what belongs here is what is SHARED, not what is small. Site
 * layout stays in site.css and the editor's own chrome stays in tools/, because
 * neither has any business in the other. Anything both surfaces need, from a
 * colour to a component, goes here and is therefore defined exactly once.
 *
 * The block at the end is written by scripts/build-client.js from client.json.
 * Do not edit it by hand, and keep it last: it overrides the defaults above.
 */

/* --- Base ------------------------------------------------------------------ */
/* `hidden` means hidden, everywhere.
 *
 * The browser's [hidden] rule is a user-agent style, so ANY author rule that
 * sets display beats it. Elements that get hidden by script are usually flex or
 * grid containers, so el.hidden = true did nothing: the editor's empty state
 * rendered on top of a capture that existed, and a dialog showed the field it
 * had just been told to hide. Both surfaces had their own copy of this fix.
 */
[hidden]{display:none !important;}
*{box-sizing:border-box;}
html{-webkit-text-size-adjust:100%;}
html,body{margin:0;}
/* Two names for one rule, because the site's markup says one and the editor's
   says the other. Cheaper than renaming every call site to prove a point. */
.visually-hidden,
.sr-only{
  position:absolute;width:1px;height:1px;padding:0;margin:-1px;
  overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0;
}

/* --- Design tokens ------------------------------------------------------- */

:root{
  /* Ground. Sampled from boutique-homes.com: body is rgb(18,20,22), its
     darkest surface rgb(13,15,17), its raised surface rgb(26,28,30). */
  --ink:#121416;              /* page ground */
  --ink-lit:#121416;          /* kept as a token because the stylesheet measures
                                 against it in places; the ground is now flat,
                                 so it is the same value as --ink */
  --ink-2:#0D0F11;            /* raised ground: top bar, dialogs */
  --ink-3:#1A1C1E;            /* the panel body and any surface that needs to
                                 read as its own plane above --ink-2 */
  --panel:#161819;            /* framed surfaces */
  --line:rgba(252,253,254,0.14);
  --line-soft:rgba(252,253,254,0.07);

  --tx:#FCFDFE;               /* 18.13:1 on --ink. Boutique's own text colour */
  --tx-2:#A6A8AC;             /*  7.75:1 on --ink. Boutique's own secondary */
  --tx-3:#8A8D92;             /*  5.54:1 on --ink */

  /* Boutique's coral is #ED5454, used on its site for "Private Sale" and for
     emphasis. It is never a large fill here: white on it is 3.50:1, which
     fails body text. As a text colour on the ground it is 5.27:1 and passes. */
  --acc:#FCFDFE;              /* primary fill, Boutique's own white button */
  --acc-hv:#E4E6E8;           /* that fill on hover */
  --acc-tx:#FF8A80;           /*  8.09:1 on --ink. The coral, lifted enough to
                                  clear AA comfortably as link and label text */
  --acc-soft:rgba(237,84,84,0.12);
  --acc-line:rgba(237,84,84,0.38);
  --on-acc:#0D0F11;           /* 18.86:1 on the white fill above */

  /* Translucent surfaces, tied to the ground rather than written as literals,
     so a re-theme cannot leave a previous client's near-black in the scrims. */
  --scrim-bar:rgba(18,20,22,0.82);
  --scrim-pin:rgba(13,15,17,0.86);
  --scrim-pin-ring:rgba(13,15,17,0.5);
  --scrim-dialog:rgba(8,9,10,0.86);
  --fill-soft:rgba(252,253,254,0.06);

  /* Severity. Muted to sit inside a photographic, matte palette: a saturated
     traffic-light green next to Boutique's coral reads as a dashboard, which
     is the opposite of what this document is. */
  --high:#FF8E8E;             /*  8.36:1 on --ink, 7.74:1 on --ink-3 */
  --moderate:#E8B872;         /* 10.14:1 on --ink,  9.38:1 on --ink-3 */
  --minor:#86C7B0;            /*  9.50:1 on --ink,  8.80:1 on --ink-3 */

  /* Marker fills. Measured the other way round from the severity tokens above:
     what matters is the numeral against its own fill, not the fill against the
     page. All three carry the same near-black numeral, which clears 8:1 on
     each. */
  --mark-ink:#12100F;         /* 8.59:1 on high, 10.42:1 on moderate,
                                 9.77:1 on minor */

  /* Framework citation hues. Five frameworks, five hues, all desaturated to
     the same degree so no single citation shouts louder than another. */
  --fw-wcag:#8FB6DE;          /*  8.72:1 */
  --fw-laws:#C0A5E0;          /*  8.53:1 */
  --fw-heuristics:#E2BA80;    /* 10.17:1 */
  --fw-platform:#85C6BB;      /*  9.49:1 */

  /* Type. Inter is Boutique's own UI face. Newsreader stands in for Reckless
     Neue, which is a licensed Displaay face the client pays for and this
     document has no right to serve; it is the closest open substitute in
     contrast, width and serif shape. */
  /* TWO FAMILIES, and the rule for which goes where.
   *
   *   --font-display  anything read as SENTENCES: page titles, finding titles,
   *                   the lede, why it matters, the framework evidence, the
   *                   recommendations, the executive summary prose, and the
   *                   large numerals. Newsreader is a variable face with optical
   *                   sizing, so it sets as a text serif at 15px and as a display
   *                   serif at 68px without loading a second file.
   *   --font-ui       anything read as INTERFACE: labels, buttons, form fields,
   *                   chips, tabs, counts, status, and every small uppercase
   *                   letterspaced label.
   *
   * The split is what the reader is doing, not where the text sits. A sentence
   * in the rail is prose; a count above it is not.
   *
   * There is deliberately no mono. It existed only to set the label style, cost
   * a webfont request on every page, and gave the two projects different answers
   * to the same question. A test fails if a third family appears. */
  /* Reading measure. Prose is set looser than interface text: a paragraph is
     read in sequence and wants the air, a label is read at a glance and does
     not. One value so every block of copy agrees. */
  --lh-prose:1.75;
  /* Both display faces carry an optical size axis, so the same family sets
     lighter at 44px than at 86px. Correct for reading, wrong for a row of
     statistics that should look like the headline above them. */
  --opsz-display:60;
  --font-ui:'Inter',-apple-system,BlinkMacSystemFont,'Segoe UI',Helvetica,Arial,sans-serif;
  --font-display:'Newsreader',Georgia,'Times New Roman',serif;

  /* Nothing is rounded. Kept as tokens rather than deleted so the two rules
     that genuinely want a circle stay explicit about it. */
  /* Editor status. These were literal hexes, and the hexes were IGC's severity
     colours, so Boutique's editor reported success in another client's green.
     Derived instead: saved reads like a minor finding, working like a moderate,
     refused like a high, in whatever palette the project actually uses. */
  --ok:var(--minor);
  --warn:var(--moderate);
  --bad:var(--high);
  --r-btn:10px;
  --r-ctl:8px;

  --nav-h:64px;
  --shell:1360px;
  --pad:clamp(20px,4vw,56px);
  --ease:0.18s ease;
}

/* --- The marker ---------------------------------------------------------- */

/* The marker. One definition, used by the published audit, by the editor's
 * canvas and by the findings list.
 *
 * It lived in three places before and drifted in all three: the site had a dark
 * disc with a coloured numeral, the editor had a solid fill, and the findings
 * list had a severity bar and a small purple numeral. Three visual languages for
 * one object, so reading a number off a capture and finding it in a list meant
 * translating between them. This file is the only place the design exists.
 *
 * SEVERITY COLOURS, and why they are these ones.
 *
 * The previous engagement put a white numeral on a saturated fill, which forced
 * the three hues down into rose, amber and emerald and still left two of them
 * under 4.5:1. Boutique's palette is muted and photographic, and three saturated
 * discs sitting on a screenshot in it read as a dashboard dropped onto a
 * document.
 *
 * Inverting the numeral solves both problems at once. The fills are the same
 * three severity tokens the rest of the site uses, and the numeral is a near
 * black taken from the ground, which measures far above the threshold on all
 * three:
 *
 *   high      #FF8E8E   #12100F numeral   8.59:1
 *   moderate  #E8B872   #12100F numeral  10.42:1
 *   minor     #86C7B0   #12100F numeral   9.77:1
 *
 * So there is no longer a trade between hue legibility and numeral legibility,
 * and the marker matches the severity colour used in the findings list rather
 * than being a darker cousin of it.
 *
 * NO DARK RIM. Against a white screenshot the three fills measure 1.68, 1.44
 * and 1.62:1, which is well under the 3:1 WCAG 1.4.11 asks of a graphical
 * object, so unlike the previous darker fills these do need separating from a
 * pale capture. That is done with a hairline ring in the page ground rather
 * than a shadow, so the marker stays flat.
 */

:root{
  --marker-high:var(--high,#FF8E8E);
  --marker-moderate:var(--moderate,#E8B872);
  --marker-minor:var(--minor,#86C7B0);
  --marker-ink:var(--mark-ink,#12100F);
  --marker-ring:var(--scrim-pin-ring,rgba(13,15,17,0.5));
  --marker-size:28px;
  --marker-lift:#fff;         /* the ring that separates a marker from the capture */
}

/* The disc itself. Positioning is left to whoever places it, because the site
   puts markers on an absolutely positioned overlay and the findings list puts
   them in a grid cell. */
.marker{
  width:var(--marker-size);height:var(--marker-size);
  border-radius:50%;padding:0;border:0;
  display:grid;place-items:center;
  font-family:var(--font-ui);
  font-variant-numeric:tabular-nums;
  box-shadow:0 0 0 1.5px var(--marker-ring);
  font-size:12px;font-weight:600;
  background:var(--acc);color:var(--marker-ink);
  /* Fallback for a marker with no severity yet. */
  --marker-pulse:var(--acc);
}
/* Each severity also names its own pulse colour, so the halo can never be a
   different hue from the disc it belongs to. */
.marker.sev-high{background:var(--marker-high);--marker-pulse:var(--marker-high);}
.marker.sev-moderate{background:var(--marker-moderate);--marker-pulse:var(--marker-moderate);}
.marker.sev-minor{background:var(--marker-minor);--marker-pulse:var(--marker-minor);}

/* The pulse is an expanding ring drawn with box-shadow on the marker itself.
 *
 * It was a scaled pseudo element with z-index:-1 first, and it was invisible:
 * a negative z-index on a child with no stacking context above it paints behind
 * the ancestors' backgrounds, and .shot-media is opaque, so the halo animated
 * away underneath the screenshot for its entire life. box-shadow has no such
 * problem - it always paints outside the border box, over whatever is there,
 * and it costs no layout because it is not part of the box model. */
.marker.is-pulsing{animation:marker-pulse 2.4s ease-out infinite;}

/* The ring is repeated as the first shadow in every keyframe. The static rule
   on .marker sets the same ring, and an animation wins over it for the whole
   property, so omitting it here made the marker lose its separation from a pale
   capture for the entire duration of the pulse. */
@keyframes marker-pulse{
  0%{box-shadow:0 0 0 1.5px var(--marker-ring), 0 0 0 0 color-mix(in srgb, var(--marker-pulse) 55%, transparent);}
  70%{box-shadow:0 0 0 1.5px var(--marker-ring), 0 0 0 13px color-mix(in srgb, var(--marker-pulse) 0%, transparent);}
  100%{box-shadow:0 0 0 1.5px var(--marker-ring), 0 0 0 0 color-mix(in srgb, var(--marker-pulse) 0%, transparent);}
}

/* Once you are interacting with it the movement is noise, and stopping the
   animation also hands the box-shadow back to the host, which is what draws the
   selected ring. An animation would otherwise win over that rule. */
.marker:hover,
.marker:focus-visible,
.marker.is-active,
.marker.is-selected{animation:none;}

@media (prefers-reduced-motion:reduce){
  .marker.is-pulsing{animation:none;}
}

/* --- Base, shared by both surfaces ---------------------------------------- */
/*
 * These lived in site.css, which the editor does not load, so the editor had no
 * reduced motion handling at all: the marker pulse animated regardless of what
 * the reader had asked their system for. The focus ring was worse, repeated in
 * four places in the editor with a different offset from the site's.
 */
button{font:inherit;color:inherit;}
:focus-visible{outline:2px solid var(--acc-tx);outline-offset:2px;}

/* --- Buttons -------------------------------------------------------------- */
/*
 * One button, used by the published site and by the editor.
 *
 * They were two: the site's outline button, and a denser filled one in
 * tools.css that happened to share the class name. Keeping both meant a change
 * to the button had to be made twice and was made once. The editor now follows
 * the site, so the only variants below that the site does not itself use are
 * .small and .danger, which exist because the editor has destructive actions
 * and a crowded toolbar and the site has neither.
 */

.btn{
  display:inline-flex;align-items:center;gap:10px;min-height:46px;padding:0 22px;
  border-radius:var(--r-btn);
  /* Sentence case, on both surfaces. Uppercase and 0.13em tracking is a label
     treatment, and it read as a different typeface next to the sentence case
     pickers and menus it sits beside in the editor. A button is a thing you
     read and act on, not a heading. */
  font-family:var(--font-ui);font-size:14px;font-weight:500;letter-spacing:0;
  border:1px solid var(--line);background:transparent;color:var(--tx);
  text-decoration:none;cursor:pointer;white-space:nowrap;
  transition:border-color var(--ease),background var(--ease);
}
.btn:hover{border-color:var(--acc-line);background:var(--acc-soft);}
/* Flat white fill, no gradient. The gradient button was the one part of Studio
   that read as template, so it is dropped. */
.btn.primary{background:var(--acc);border-color:var(--acc);color:var(--on-acc);font-weight:500;}
.btn.primary:hover{background:var(--acc-hv);border-color:var(--acc-hv);}

.btn:disabled{opacity:0.4;cursor:default;}
.btn.small{min-height:34px;padding:0 14px;font-size:13px;}
/* Destructive actions. Not used anywhere on the site, kept here anyway so the
   button has one definition rather than nearly one.

   Outline only, deliberately. A filled destructive button is the loudest thing
   in a dialog whose primary action is Done, and Delete finding sits next to it. */
.btn.danger{color:var(--bad);border-color:color-mix(in srgb, var(--bad) 45%, transparent);}
.btn.danger:hover{border-color:var(--bad);background:color-mix(in srgb, var(--bad) 12%, transparent);}

/* --- Dialogs -------------------------------------------------------------- */
/*
 * One dialog, used by the published audit and by the editor.
 *
 * The site's is the reference: an --ink-2 panel on a scrim, a header that does
 * not scroll, and a body that is the only scrolling region. The editor had its
 * own .sheet doing the same job in slightly different numbers, plus one part the
 * site has no use for, a footer, because the editor's dialogs commit something
 * and the site's only ever read.
 *
 * The site opens a div overlay and the editor opens a native <dialog>. The
 * native element is the better of the two, since focus trapping, Escape and
 * inerting the page behind all come free, so the rules below are written to fit
 * either and the site can follow when someone has time to test it.
 */
.dialog{
  position:relative;width:100%;max-width:none;border-radius:var(--r-btn);
  background:var(--ink-2);border:1px solid var(--line);padding:clamp(26px,3.4vw,44px);
  overflow-y:auto;overscroll-behavior:contain;
}
/* [open] is load bearing on the native element.
 *
 * A <dialog> is display:none until it is opened, and that comes from the user
 * agent sheet, which any author display rule outranks. Setting display:flex on
 * dialog.dialog unconditionally put all five editor dialogs on the page at once,
 * stacked, permanently. Same mistake as the [hidden] one: a layout rule quietly
 * beating a rule that was doing real work. */
.dialog.finding-dialog,
.dialog.exec-dialog,
dialog.dialog[open]{
  display:flex;flex-direction:column;border-radius:var(--r-btn);padding:0;overflow:hidden;
}
/* The native element has to carry what .dialog-overlay does for the site: its
   own inset from the viewport, since there is no wrapper to pad it. */
dialog.dialog{
  color:var(--tx);
  width:calc(100vw - 2 * clamp(10px,2vw,28px));
  height:calc(100vh - 2 * clamp(10px,1.8vh,28px));
  max-width:none;max-height:none;
  background:var(--ink-2);border:1px solid var(--line);
}
dialog.dialog::backdrop{background:var(--scrim-dialog);}

.dialog-close{
  position:absolute;top:14px;right:14px;z-index:2;width:38px;height:38px;border-radius:var(--r-ctl);
  border:1px solid var(--acc);background:var(--acc);color:var(--on-acc);
  font-size:19px;line-height:1;cursor:pointer;transition:background var(--ease),border-color var(--ease);
}
/* The button stays 38px so the header is unchanged; only the hit area grows. */
.dialog-close::after{
  content:"";position:absolute;top:50%;left:50%;
  width:44px;height:44px;transform:translate(-50%,-50%);
}
.dialog-close:hover{background:var(--acc-hv);border-color:var(--acc-hv);}

.dialog-head,
.finding-head,
.exec-head{
  position:relative;flex:none;
  padding:clamp(26px,3.4vw,44px) 52px 22px clamp(26px,3.4vw,44px);
  background:var(--ink-2);border-bottom:1px solid var(--line);
}
.dialog-body,
.finding-body,
.exec-body{
  flex:1;min-height:0;overflow-y:auto;overscroll-behavior:contain;
  padding:26px clamp(26px,3.4vw,44px) clamp(30px,4vw,46px);
}
/* The line above the title. On the site it names the finding; in the editor
   it names what is being edited. Same role, so the same type. */
.dialog-eyebrow,
.finding-num{
  /* Sentence case, on both surfaces. Uppercase and 0.13em tracking is a label
     treatment, and it read as a different typeface next to the sentence case
     pickers and menus it sits beside in the editor. A button is a thing you
     read and act on, not a heading. */
  font-family:var(--font-ui);font-size:14px;font-weight:500;letter-spacing:0;
  color:var(--acc-tx);margin-bottom:12px;
}

/* The dialog's title, one type style. The editor had its own 16px UI size,
   which is the kind of local override that lets two components drift apart
   again while still looking shared. */
.dialog-head h2,
.finding-head h2{
  margin:0;font-family:var(--font-display);font-weight:400;
  font-size:clamp(25px,3.2vw,38px);line-height:1.08;letter-spacing:-0.01em;
}

/* The editor only. A dialog that commits something needs somewhere to put the
   commit, and nothing on the site commits anything. */
.dialog-foot{
  flex:none;padding:14px clamp(26px,3.4vw,44px);border-top:1px solid var(--line);
  display:flex;flex-direction:column;gap:10px;background:var(--ink-2);
}
.dialog-actions{display:flex;align-items:center;gap:10px;}

/* --- The top bar ----------------------------------------------------------- */
/* Sticky, full width, translucent. The editor had its own solid bar doing the
   same job at a different height, which is why the two never quite lined up
   when you flipped between them. */
.topbar{
  position:sticky;top:0;z-index:50;height:var(--nav-h);
  display:flex;align-items:center;justify-content:space-between;gap:16px;
  padding-inline:var(--pad);
  /* Translucent rather than solid, so the glow behind it stays continuous with
     the masthead instead of being sliced off by an opaque bar. */
  background:var(--scrim-bar);
  backdrop-filter:blur(16px) saturate(1.3);
  -webkit-backdrop-filter:blur(16px) saturate(1.3);
  border-bottom:1px solid var(--line);
}
/* The editor carries three groups where the site carries two, so it grids.
   Not used by the site, kept here so the bar has one definition. */
.topbar--three{display:grid;grid-template-columns:1fr auto 1fr;}

/* The content column, shared. It lived in site.css, which the editor does not
   load, so adding the class to the editor's layout silently did nothing. */
/* Full bleed. The shell used to cap at --shell and centre, which on a wide
   screen left the page floating in the middle while the rules above and
   below it ran edge to edge. The padding is the only inset now, and it is
   the same on both sides of both surfaces. */
.shell{max-width:none;margin:0;padding-inline:var(--pad);}

/* --- The audit layout ------------------------------------------------------ */
/*
 * Evidence on the left, findings on the right, in the same proportion on the
 * published page and in the editor.
 *
 * The editor used a fixed 360px rail. At any real screen width that is far
 * narrower than the published one, so a rail that looked balanced while
 * authoring was not what the client saw, and checking meant saving and opening
 * the site. The columns are now the same ratio in both, inside the same 1360px
 * shell, so the editor is a preview of the page rather than an approximation.
 */
.layout{display:grid;grid-template-columns:minmax(0,1.62fr) minmax(318px,1fr);}
.mod-body{
  display:grid;grid-template-columns:minmax(0,1.62fr) minmax(318px,1fr);
  border-bottom:1px solid var(--line);
}

.mod-evidence,
.stage{
  padding:clamp(24px,3vw,36px) clamp(24px,3vw,40px) clamp(30px,4vw,46px) 0;
  border-right:1px solid var(--line);min-width:0;
}
.mod-rail,
.rail{padding:clamp(24px,3vw,36px) 0 clamp(30px,4vw,46px) clamp(24px,3vw,38px);min-width:0;}
/* The editor only. It is a fixed app shell whose top bar has to stay put, so its
   two panes scroll independently; the published page scrolls as one document.
   That is the entire difference between the two layouts. */
.layout{flex:1;min-height:0;}
.stage{overflow:auto;}
.rail{overflow-y:auto;}

/* --- The capture ----------------------------------------------------------- */
/*
 * The screenshot, its frame, and the markers on it. This is the centre of both
 * surfaces and it had drifted: the editor's frame was rounded and clipped, the
 * published one square, so a capture never looked in the editor quite the way it
 * looked to the client. The published one wins, because that is the one that
 * ships.
 */
.shot-media,
.shot{position:relative;border:1px solid var(--line);background:var(--panel);}
.shot-media img,
.shot img{width:100%;height:auto;display:block;}
.shot-caption,
.shot-hint,
.hint{
  margin:12px 0 0;font-family:var(--font-ui);font-size:10px;letter-spacing:0.12em;
  text-transform:uppercase;color:var(--tx-3);
}
/* Markers are centred on their point by transform on both surfaces. The editor
   used a negative margin off --marker-size, which needed updating every time the
   marker changed size and quietly disagreed when it did not. */
.shot-hint{margin-top:16px;text-align:center;}
.pin-btn,
.pin{position:absolute;transform:translate(-50%,-50%);cursor:pointer;transition:transform var(--ease);}

/* --- Switching between variations ------------------------------------------ */
/* Underlined tabs on both. The editor used bordered pills, which read as filters
   rather than as the same "which view am I looking at" control the client uses. */
.device-tabs{display:flex;flex-wrap:wrap;gap:6px clamp(12px,1.8vw,24px);margin-bottom:22px;}
.device-tab{
  position:relative;background:0;border:0;border-bottom:1px solid transparent;padding:0 0 8px;
  cursor:pointer;font-family:var(--font-ui);font-size:11px;letter-spacing:0.13em;
  text-transform:uppercase;color:var(--tx-3);transition:color var(--ease),border-color var(--ease);
}
.device-tab:hover{color:var(--tx-2);}
.device-tab[aria-selected="true"],
.device-tab:has(input:checked){color:var(--tx);border-bottom-color:var(--acc);}
.device-tab input{position:absolute;opacity:0;width:0;height:0;}

/* --- The findings list ---------------------------------------------------- */
/*
 * One row design, used by the published audit and by the editor's rail.
 * The editor had its own: a filled disc and a single line of title, so the
 * column you author in looked nothing like the column the client reads.
 */
.rail-head{display:flex;align-items:baseline;justify-content:space-between;gap:16px;padding:0 14px 6px;}
.rail-head h2,
.rail-head span,
.rail h2{
  margin:0;font-family:var(--font-ui);font-size:11px;font-weight:400;
  letter-spacing:0.13em;text-transform:uppercase;color:var(--tx-3);
}
/* Findings rows.
   Severity is a colour bar down the left edge rather than a word, so the mix
   of a module is readable from the shape of the column before anything in it
   is read. The bar is the row's only saturated element; the title, summary and
   citations are a single grey ramp, which is what keeps a dense column calm. */
/* scroll-margin clears the sticky top bar when a diagnosis link lands here. */
.find-item{scroll-margin-top:calc(var(--nav-h) + 24px);
  display:grid;grid-template-columns:3px minmax(0,1fr);gap:14px;width:100%;
  padding:16px 14px;border:0;border-top:1px solid var(--line-soft);border-radius:var(--r-ctl);
  background:transparent;text-align:left;cursor:pointer;transition:background var(--ease);
}
.find-item:first-of-type{border-top:1px solid var(--line);}
.find-item::before{content:"";border-radius:2px;background:var(--tx-3);margin:2px 0;}
.find-item.high::before{background:var(--high);}
.find-item.moderate::before{background:var(--moderate);}
.find-item.minor::before{background:var(--minor);}
.find-item:hover{background:var(--acc-soft);}
.find-body{display:block;min-width:0;}
.find-top{display:flex;align-items:baseline;gap:14px;}
.find-item h3{
  margin:0;font-family:var(--font-display);font-size:15px;font-weight:500;line-height:1.4;letter-spacing:-0.005em;color:var(--tx);
}
/* The number here IS the marker from the capture, so it carries the same
   severity fill and the same numeral ink. It used to be an accent ring, which
   meant the row and the capture disagreed about what colour finding 1 was: the
   disc on the screenshot was amber, the disc beside its title was coral. The
   whole point of printing a number in both places is that they match. */
.find-marker{
  margin-left:auto;flex-shrink:0;width:22px;height:22px;border-radius:50%;
  display:grid;place-items:center;font-family:var(--font-ui);font-size:11px;font-weight:500;
  border:0;background:var(--tx-3);color:var(--marker-ink);
  transition:transform var(--ease);
}
.find-item.high .find-marker{background:var(--marker-high);}
.find-item.moderate .find-marker{background:var(--marker-moderate);}
.find-item.minor .find-marker{background:var(--marker-minor);}
/* Nudged rather than recoloured on hover: recolouring would break the one thing
   it is here to do. */
.find-item:hover .find-marker,.find-item:focus-visible .find-marker{transform:scale(1.12);}
/* Two lines of the finding's own "why it matters". Clamped rather than
   truncated server-side so the full sentence stays in the DOM for search and
   for anyone reading with a screen reader. */
.find-sum{line-height:var(--lh-prose);font-family:var(--font-display);
  margin:7px 0 0;font-size:13.5px;color:var(--tx-2);
  display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;
  line-clamp:2;overflow:hidden;
}
.find-refs{display:flex;gap:6px;margin-top:11px;flex-wrap:wrap;}
.find-refs span{
  font-family:var(--font-ui);font-size:10px;letter-spacing:0.07em;
  padding:2px 8px;border:1px solid var(--line-soft);border-radius:var(--r-ctl);
  background:var(--fill-soft);color:var(--tx-3);white-space:nowrap;cursor:help;
}
/* Editor only: a finding with no marker fails the build, so it is called out
   in the row rather than discovered at save time. */
.find-flag{display:inline-block;margin-top:9px;font-family:var(--font-ui);font-size:9.5px;letter-spacing:0.1em;text-transform:uppercase;color:var(--warn);}
.find-item.is-active{background:var(--acc-soft);}
/* Editor only, and scoped to the editor's rail so it does not argue with the
   published row's cursor. Rows are dragged to reorder the findings, which
   renumbers them and every marker that points at one. */
.rail .find-item{cursor:grab;}
.rail .find-item:active{cursor:grabbing;}
li.is-dragging{opacity:0.4;}
li.is-over{box-shadow:inset 0 2px 0 var(--acc);}


/* --- Breakpoints ----------------------------------------------------------- */
/* Below this the two columns stack and the divider becomes a rule underneath the
   capture. The editor had its own version of this at 900px which no longer reset
   anything, because the divider had moved to the evidence column. */
/* The shared dialog tightens on a small screen. This lived in site.css, so
   the editor's dialog kept its full padding at widths where the published
   one had already given it up. */
@media (max-width:640px){
  .dialog{padding:24px 18px 30px;}
  .dialog.finding-dialog,.dialog.exec-dialog{padding:0;}
  .finding-head,.exec-head{padding:24px 44px 18px 18px;}
  .finding-body,.exec-body{padding:20px 18px 30px;}
}

/* On a narrow screen the row gives up its severity bar for a readable gutter.
   This was in site.css, inside a breakpoint, so the editor's rows kept the
   3px column at widths where the published ones had already dropped it. */
@media (max-width:640px){
  .find-item{grid-template-columns:24px minmax(0,1fr);gap:10px;}
}

@media (max-width:1120px){
  .mod-body,
  .layout,
  .mod-page--mobile .mod-body{grid-template-columns:minmax(0,1fr);}
  .mod-evidence,
  .stage{border-right:0;border-bottom:1px solid var(--line);padding-right:0;}
  .mod-rail,
  .rail{padding-left:0;}
}

/* --- Per client, generated ------------------------------------------------ */

/* client:tokens:start */
/* GENERATED by scripts/build-client.js from client.json. Do not edit.
   Loaded after site.css, so anything here overrides the documented
   defaults. Change client.json and run `npm run build`. */

:root{
  --acc:#FCFDFE;
  --acc-hv:#E4E6E8;
  --acc-tx:#FF8A80;
  --on-acc:#0D0F11;
  --acc-soft:rgba(237,84,84,0.12);
  --r-btn:10px;
  --r-ctl:8px;
  --font-ui:'Inter',-apple-system,BlinkMacSystemFont,'Segoe UI',Helvetica,Arial,sans-serif;
  --font-display:'Newsreader',Georgia,'Times New Roman',serif;
}
/* client:tokens:end */

/* The way back to the capture, shown only when the finding dialog is opened
   from the diagnosis, where there is no capture on screen behind it. */
.finding-source{margin:26px 0 0;padding-top:18px;border-top:1px solid var(--line);}
.finding-source-link{
  font-family:var(--font-ui);font-size:11px;letter-spacing:0.13em;text-transform:uppercase;
  color:var(--acc-tx);text-decoration:none;
}
.finding-source-link:hover{text-decoration:underline;}
.finding-source-link::after{content:" \2197";}
