/* ======================================================================
   ReportLog — the Client-First layer
   ======================================================================

   WHAT THIS IS. A stylesheet written to Finsweet's Client-First naming
   conventions, the ones the Relume library is built on: a small vocabulary
   of structure, spacing, typography and component classes that every screen
   is assembled from, rather than a new rule written for every new box.

   WHAT IT IS NOT. It is not a redesign and it holds no design decisions of
   its own. Every colour it uses is a palette token and every shape it uses
   is a theme token, so an operator's chosen look reaches a screen built out
   of these classes exactly as it reaches one built the old way. The two
   axes still hold:

     PALETTE owns every colour.   Nothing here names a colour value.
     THEME owns type, borders, shadows, radii and width. Nothing here
     names a font family, a radius or a page width of its own either.

   Both are asserted by scripts/selftest.js. If you find yourself wanting to
   type a hex value or a pixel radius in this file, the thing you want
   belongs in a palette or a theme.

   SAFE TO ADD BEFORE IT IS USED. There is not one element selector in this
   file. Every rule is a class, and no class here is used anywhere in the
   existing page (checked). So loading it changes nothing on any screen
   until a screen is rewritten to use it, one screen at a time.

   LOADED LAST. It comes after the page's own stylesheet so that a utility
   class wins over a component's own rule, which is the whole point of a
   utility class. That is Client-First's own ordering.

   THE NAMING, IN ONE BREATH
   -------------------------
     page-wrapper / main-wrapper       the page itself
     section_<name>                    one band of the page
     padding-global                    the left and right gutter, once
     container-small|medium|large      the measure inside the gutter
     padding-section-small|medium|large   the band's top and bottom air
     <name>_component                  a thing you could lift out whole
     <name>_item, <name>_wrapper       its parts
     is-<variant>                      a combo class changing the one above
     text-size-*, heading-style-*      type, without picking an h-level
     margin-* / padding-*              spacing, direction plus size
     spacer-*                          an empty div holding air open
     hide, hide-tablet, …              visibility

   The rule that keeps it readable: a class either says WHAT SOMETHING IS
   (`report-card_component`) or applies ONE decided value (`text-size-small`).
   Never a class that means "this particular box on this particular screen".

   See docs/client-first.md for how to build a screen out of this. The
   palette and theme axes underneath it are declared in public/tokens.css,
   which states each one and what it may decide; /styleguide shows every
   value they produce, on one page, with a bar that changes both.
   ====================================================================== */

/* ---- the scales -------------------------------------------------------
   Everything below is measured in these and nothing invents a value.
   `rem` throughout: the page's root size is untouched, so 1rem is 16px and
   a reader who has set a larger type size in their browser gets a page that
   grows with it rather than one pinned to pixels. */
:root{
  /* Space. Client-First's own steps, and the only ones offered: a value
     between two of these is a value somebody typed by eye. */
  --space--tiny:0.25rem;
  --space--xxsmall:0.5rem;
  --space--xsmall:1rem;
  --space--small:1.5rem;
  --space--medium:2rem;
  --space--large:3rem;
  --space--xlarge:4rem;
  --space--xxlarge:5rem;
  --space--huge:6rem;
  --space--xhuge:8rem;
  --space--xxhuge:12rem;

  /* The gutter down both sides of every screen. `max()` with the safe-area
     inset, as the rest of the site does it, so nothing sits under the
     rounded corner or the camera notch on a phone. */
  --space--gutter:max(1.25rem,env(safe-area-inset-left,0px));
  --space--gutter-right:max(1.25rem,env(safe-area-inset-right,0px));

  /* The measure. The widest container is the THEME's width, not a number
     chosen here — width belongs to the theme and each theme states its own.
     The two narrower ones are for a column inside that, a form or a notice,
     and are plain sizes because they are about reading length rather than
     about the shape of the site. */
  --size--container-small:30rem;
  --size--container-medium:48rem;
  --size--container-large:var(--page-max,64rem);

  /* Type. Six steps and no more, the same reasoning as the space scale. */
  --text--tiny:0.75rem;
  --text--small:0.875rem;
  --text--regular:1rem;
  --text--medium:1.125rem;
  --text--large:1.375rem;
  --text--xlarge:1.75rem;

  /* Headings, fluid between a phone and a desktop so no breakpoint has to
     restate them. The floor is the phone size and the ceiling the desktop
     one; both are real steps, the middle term is just the ramp between. */
  --text--h1:clamp(2rem,1.45rem + 2.4vw,3rem);
  --text--h2:clamp(1.625rem,1.3rem + 1.5vw,2.25rem);
  --text--h3:clamp(1.375rem,1.2rem + 0.9vw,1.75rem);
  --text--h4:1.375rem;
  --text--h5:1.125rem;
  --text--h6:1rem;

  /* How tall a line is. Tight for a heading, open for reading. */
  --leading--heading:1.15;
  --leading--body:1.55;

  /* The height of anything you tap. 2.75rem is 44px at the default root
     size, which is the smallest target iOS and Android both call reachable.
     Written once here so no component quietly comes in under it. */
  --size--tap:2.75rem;
}

/* ======================================================================
   1. STRUCTURE
   The four classes every screen is built from, in this order, always:

     <div class="page-wrapper">
       <main class="main-wrapper">
         <section class="section_intro">
           <div class="padding-global">
             <div class="container-large">
               <div class="padding-section-medium"> … </div>

   The gutter is set in ONE place (padding-global) and the measure in ONE
   place (container-*), so a screen cannot end up with a left edge that
   disagrees with the screen before it.
   ====================================================================== */

.page-wrapper{display:flex;flex-direction:column;min-height:100vh;min-height:100svh}
.main-wrapper{flex:1 0 auto;display:block}

/* A section is a band of the page. It carries no padding and no width of
   its own — those are the two classes inside it. Naming it after what it
   holds (`section_intro`, `section_board`) is what makes a long page
   readable in the markup, so this bare class is only the shared base. */
.section{position:relative}

.padding-global{
  padding-left:var(--space--gutter);
  padding-right:var(--space--gutter-right);
}
/* The one thing that may live inside padding-global and ignore it: a strip
   that has to run to both edges of the screen, like the bar under the nav. */
.padding-global.is-bleed{padding-left:0;padding-right:0}

.container-small{width:100%;max-width:var(--size--container-small);margin-left:auto;margin-right:auto}
.container-medium{width:100%;max-width:var(--size--container-medium);margin-left:auto;margin-right:auto}
.container-large{width:100%;max-width:var(--size--container-large);margin-left:auto;margin-right:auto}

/* The air above and below a band. Three sizes, and they shrink on a phone
   where a desktop's 8rem of nothing is most of the screen. */
.padding-section-small{padding-top:var(--space--medium);padding-bottom:var(--space--medium)}
.padding-section-medium{padding-top:var(--space--large);padding-bottom:var(--space--large)}
.padding-section-large{padding-top:var(--space--xlarge);padding-bottom:var(--space--xlarge)}
@media screen and (min-width:48rem){
  .padding-section-small{padding-top:var(--space--large);padding-bottom:var(--space--large)}
  .padding-section-medium{padding-top:var(--space--xlarge);padding-bottom:var(--space--xlarge)}
  .padding-section-large{padding-top:var(--space--huge);padding-bottom:var(--space--huge)}
}

/* ======================================================================
   2. TYPOGRAPHY
   heading-style-* sets how something LOOKS; the h-level in the markup says
   what it IS. They are separate on purpose: a screen often needs an h2 that
   reads quietly, and the wrong fix is to make it an h4 and break the
   outline a screen reader announces.
   ====================================================================== */

.heading-style-h1,
.heading-style-h2,
.heading-style-h3,
.heading-style-h4,
.heading-style-h5,
.heading-style-h6{
  font-family:var(--cond,inherit);
  font-weight:var(--h1-weight,700);
  letter-spacing:var(--h1-tracking,normal);
  line-height:var(--leading--heading);
  text-transform:var(--display-transform,none);
  margin:0;
}
.heading-style-h1{font-size:var(--text--h1)}
.heading-style-h2{font-size:var(--text--h2)}
.heading-style-h3{font-size:var(--text--h3)}
.heading-style-h4{font-size:var(--text--h4)}
.heading-style-h5{font-size:var(--text--h5)}
.heading-style-h6{font-size:var(--text--h6)}

/* A short line above a heading. Small, spaced out, upper case — the site's
   existing eyebrow, said in this vocabulary. */
.heading-style-eyebrow{
  font-family:var(--cond,inherit);
  font-size:var(--text--tiny);
  font-weight:700;
  letter-spacing:var(--label-tracking,.09em);
  line-height:1.3;
  text-transform:uppercase;
  color:var(--muted);
  margin:0;
}

.text-size-tiny{font-size:var(--text--tiny);line-height:var(--leading--body)}
.text-size-small{font-size:var(--text--small);line-height:var(--leading--body)}
.text-size-regular{font-size:var(--text--regular);line-height:var(--leading--body)}
.text-size-medium{font-size:var(--text--medium);line-height:var(--leading--body)}
.text-size-large{font-size:var(--text--large);line-height:1.4}
.text-size-xlarge{font-size:var(--text--xlarge);line-height:1.3}

.text-weight-normal{font-weight:400}
.text-weight-medium{font-weight:500}
.text-weight-semibold{font-weight:600}
.text-weight-bold{font-weight:700}

.text-align-left{text-align:left}
.text-align-center{text-align:center}
.text-align-right{text-align:right}

/* Colour, and every one of these is a palette token. `text-color-*` names
   the JOB the text does, not the colour it comes out — which is what lets
   the same class read correctly in a light palette and a dark one. */
.text-color-ink{color:var(--ink)}
.text-color-secondary{color:var(--ink-2)}
.text-color-muted{color:var(--muted)}
.text-color-action{color:var(--act-dk)}
.text-color-serious{color:var(--seal)}
.text-color-confirmed{color:var(--verify)}
.text-color-on-solid{color:var(--on-solid)}
.text-color-on-deep{color:var(--color--text-on-deep)}
.text-color-inherit{color:inherit}

.text-style-allcaps{text-transform:uppercase;letter-spacing:var(--label-tracking,.09em)}
.text-style-italic{font-style:italic}
.text-style-nowrap{white-space:nowrap}
.text-style-strikethrough{text-decoration:line-through}
.text-style-mono{font-family:var(--mono,ui-monospace,monospace)}
/* Long, unbroken things a reader is meant to be able to see all of: a
   reference, a hash, an address. Breaks anywhere rather than pushing the
   page sideways on a phone. */
.text-style-break{overflow-wrap:anywhere;word-break:break-word}
/* Cut off after a set number of lines, with the ellipsis the browser draws.
   Never for anything a decision rests on — a truncated report is a report
   somebody has half read. */
.text-style-clamp-2,
.text-style-clamp-3{display:-webkit-box;-webkit-box-orient:vertical;overflow:hidden}
.text-style-clamp-2{-webkit-line-clamp:2}
.text-style-clamp-3{-webkit-line-clamp:3}

.text-style-link{color:inherit;text-decoration:underline;text-underline-offset:.15em}
.text-style-link:hover{text-decoration-thickness:2px}

/* Prose written somewhere else — a blurb, a moderator's note, an emailed
   paragraph. The ONLY place in this file where a rule reaches a bare
   element, and it is fenced inside this one class for that reason. */
.text-rich-text > * + *{margin-top:var(--space--xsmall)}
.text-rich-text p{margin:0;line-height:var(--leading--body)}
.text-rich-text h2,
.text-rich-text h3,
.text-rich-text h4{font-family:var(--cond,inherit);line-height:var(--leading--heading);margin:0}
.text-rich-text h2{font-size:var(--text--h3)}
.text-rich-text h3{font-size:var(--text--h4)}
.text-rich-text h4{font-size:var(--text--h5)}
.text-rich-text ul,
.text-rich-text ol{margin:0;padding-left:1.25rem}
.text-rich-text li + li{margin-top:var(--space--tiny)}
.text-rich-text a{color:inherit;text-decoration:underline;text-underline-offset:.15em}
/* The gap between two things. `.text-rich-text > * + *` above is (0,1,0) and
   the `margin:0` resets on p, ul and the headings are (0,1,1), so the gap
   lost and consecutive paragraphs sat flush. Restated at the resets' own
   specificity, after them, for the elements that carry a reset. */
.text-rich-text > * + p,
.text-rich-text > * + ul,
.text-rich-text > * + ol,
.text-rich-text > * + h2,
.text-rich-text > * + h3,
.text-rich-text > * + h4{margin-top:var(--space--xsmall)}
/* A heading that follows something starts a new group, so it gets more. */
.text-rich-text > * + h2,
.text-rich-text > * + h3,
.text-rich-text > * + h4{margin-top:var(--space--medium)}
.text-rich-text code{font-family:var(--mono,ui-monospace,monospace);font-size:.92em;
  background-color:var(--color--background-alt);padding:.1em .35em;border-radius:var(--radius-sm,0)}

/* ======================================================================
   3. BUTTONS
   `.button` is the action. `is-*` changes it.

   GOLD CARRIES DARK TEXT, always — white on gold measures 2.08:1 and fails
   outright, which is why the pair is two tokens rather than one colour and
   an assumption. Status colour never becomes a button: teal means a
   moderator confirmed something and crimson means serious, and a button
   wearing either would turn a signal into decoration.
   ====================================================================== */

.button{
  display:inline-flex;align-items:center;justify-content:center;gap:var(--space--xxsmall);
  min-height:var(--size--tap);
  padding:0.625rem 1.25rem;
  border:var(--border-main,1px) solid transparent;
  border-radius:var(--radius,0);
  background-color:var(--act);
  color:var(--act-fg);
  font-family:var(--cond,inherit);
  font-size:var(--text--regular);
  font-weight:700;
  line-height:1.2;
  letter-spacing:var(--label-tracking,.09em);
  text-transform:uppercase;
  text-align:center;
  text-decoration:none;
  cursor:pointer;
  -webkit-appearance:none;appearance:none;
}
.button{box-shadow:var(--shadow,none);
  transition:background-color .13s ease,color .13s ease,transform .08s ease,box-shadow .08s ease}
.button:hover{background-color:var(--act-dk);color:var(--act-fg)}
.button:active{transform:var(--press,none)}
/* The outline a keyboard leaves. Never removed, only made legible: two
   pixels of the page's own focus colour, held off the edge so it reads on
   a filled button as well as a bare one. */
.button:focus-visible,
.form_input:focus-visible,
.form_select:focus-visible,
.form_textarea:focus-visible,
.choice_item:focus-within{outline:2px solid var(--focus);outline-offset:2px}

.button.is-secondary{background-color:var(--card);color:var(--ink);border-color:var(--ink)}
.button.is-quiet{background-color:transparent;color:var(--ink-2);border-color:var(--rule)}
.button.is-solid{background-color:var(--solid);color:var(--on-solid);border-color:var(--solid)}
/* The one control deliberately under the 44px tap height: it is the Change
   link beside an answer, not something somebody hunts for on a phone. It
   still clears the 24px WCAG 2.2 AA minimum with room to spare. */
.button.is-small{min-height:2.25rem;padding:0.375rem 0.75rem;font-size:var(--text--small);box-shadow:none}
.button.is-large{padding:0.875rem 1.75rem;font-size:var(--text--medium)}
.button.is-full{width:100%;padding:1rem;font-size:var(--text--small)}

/* States come after the flavours: they share a specificity, so order decides. */
/* The quieter flavours fill in on hover. A view the reader is on (`.active`, set
   by the script that owns the tabs) looks the same. */
.button.is-secondary:hover,
.button.is-quiet:hover,
.button.active{background-color:var(--solid);color:var(--on-solid);border-color:var(--solid)}
.button.is-solid:hover{background-color:var(--solid-hover);border-color:var(--solid-hover);color:var(--on-solid)}
/* THE ONE DESTRUCTIVE BUTTON, and it is worth saying why it exists at all.

   The look's own rule is that crimson is status only and never a button
   (public/tokens.css, top of file), so that a serious mark stays a signal
   rather than becoming decoration. This is the exception and it is asked for
   by name: handing the deployment over is the single action on any screen
   that cannot be undone, and it is the meaning crimson already carries —
   serious. It is not a second action colour. Gold is still "the action you
   came to take"; this is "the action you came to take and should not have".

   OUTLINED, not filled, until it is hovered or focused. A filled crimson
   button sitting in a panel would read as the page's primary action from
   across the room, which is the opposite of what it is for; an outlined one
   reads as a door you have to mean to open. Filling on hover is what tells
   somebody with the pointer on it that they are about to do the thing.

   Status crimson is dark in every palette, so it carries white when filled —
   --on-solid is not safe here and --color--on-serious is the token for it. */
.button.is-danger{background-color:transparent;color:var(--color--status-serious);
  border-color:var(--color--status-serious)}
.button.is-danger:hover,
.button.is-danger:active{background-color:var(--color--status-serious);
  color:var(--color--on-serious);border-color:var(--color--status-serious)}
.button[disabled],.button.is-disabled{opacity:.55;cursor:not-allowed}

/* Several buttons in a row, wrapping onto the next line on a phone rather
   than squeezing. */
.button-group{display:flex;flex-wrap:wrap;gap:var(--space--xxsmall);align-items:center}
.button-group.is-right{justify-content:flex-end}
.button-group.is-spread{justify-content:space-between}

/* ======================================================================
   4. FORM
   One question, one field, one place the error goes. The card the question
   sits on is `choice_component` below.
   ====================================================================== */

.form_field-wrapper{display:flex;flex-direction:column;gap:var(--space--tiny)}
.form_label{
  font-family:var(--cond,inherit);
  font-size:var(--text--small);
  font-weight:700;
  letter-spacing:var(--label-tracking,.09em);
  text-transform:uppercase;
  color:var(--ink-2);
}
.form_help{font-size:var(--text--small);color:var(--muted);line-height:var(--leading--body)}

.form_input,
.form_select,
.form_textarea{
  width:100%;
  min-height:var(--size--tap);
  padding:0.625rem 0.75rem;
  /* --field, not --rule: a control's border has to clear 3:1 to meet WCAG
     for a user interface component, where a decorative hairline does not. */
  border:var(--border-main,1px) solid var(--field);
  border-radius:var(--radius-sm,0);
  background-color:var(--card);
  color:var(--ink);
  font-family:var(--sans,inherit);
  /* 1rem exactly. Anything smaller and Safari on iOS zooms the page in when
     the field takes focus, and never zooms back out. */
  font-size:1rem;
  line-height:var(--leading--body);
  -webkit-appearance:none;appearance:none;
}
.form_textarea{min-height:8rem;resize:vertical}
/* The select keeps the browser's own arrow. Stripping it means drawing one,
   and the only ways to draw one are an image with a colour baked into it or
   a wrapper element around every select — a caret that stops matching the
   palette, or a component nobody remembers to use. */
.form_select{-webkit-appearance:auto;appearance:auto;padding-right:0.5rem}
.form_input::placeholder,.form_textarea::placeholder{color:var(--muted)}
.form_input.is-invalid,.form_select.is-invalid,.form_textarea.is-invalid{border-color:var(--seal)}

/* Said out loud by a screen reader when it changes, which is the only
   reason an error message is worth writing. Give it role="alert". */
.form_error{
  display:none;
  padding:var(--space--xxsmall) var(--space--xsmall);
  border-left:3px solid var(--seal);
  background-color:var(--seal-bg);
  color:var(--seal);
  font-size:var(--text--small);
  line-height:var(--leading--body);
}
.form_error.is-shown{display:block}

/* ---- a choice, as a tile ----------------------------------------------
   The whole tile is the label, so the tap target is the tile and not the
   twelve pixels of the radio button. The input stays a real input,
   positioned under the tick rather than hidden, so the keyboard, the
   screen reader and the form all keep working. */
.choice_list{display:flex;flex-direction:column;gap:var(--space--xxsmall);margin:0;padding:0;list-style:none}
.choice_item{
  position:relative;
  display:flex;align-items:flex-start;gap:var(--space--xsmall);
  min-height:var(--size--tap);
  padding:var(--space--xsmall);
  border:var(--border-main,1px) solid var(--rule);
  border-radius:var(--radius-sm,0);
  background-color:var(--card);
  cursor:pointer;
}
.choice_item:hover{border-color:var(--field)}
.choice_input{flex:none;width:1.125rem;height:1.125rem;margin-top:.2rem;accent-color:var(--act-dk)}
.choice_text{display:flex;flex-direction:column;gap:2px;min-width:0}
.choice_title{font-weight:700;line-height:1.3}
.choice_note{font-size:var(--text--small);color:var(--muted);line-height:var(--leading--body)}
/* Chosen. A border weight AND a tint, never colour alone: colour alone is
   invisible to a reader who cannot see it and to one on a bad screen. */
.choice_item.is-selected{border-color:var(--ink);box-shadow:inset 0 0 0 1px var(--ink)}

/* ======================================================================
   5. LAYOUT HELPERS
   Flex and grid arrangements, named for what they do. A grid is columns and
   a gap and nothing else — any box inside it styles itself.
   ====================================================================== */

.layout_grid{display:grid;grid-template-columns:1fr;gap:var(--space--small)}
@media screen and (min-width:48rem){
  .layout_grid.is-2col{grid-template-columns:repeat(2,1fr)}
  .layout_grid.is-3col{grid-template-columns:repeat(3,1fr)}
  .layout_grid.is-sidebar{grid-template-columns:minmax(0,1fr) 18rem}
}
/* As many columns as fit, each at least the width named. No breakpoint
   needed and none of the columns ever goes narrower than it can read at. */
.layout_grid.is-auto{grid-template-columns:repeat(auto-fit,minmax(min(16rem,100%),1fr))}
.layout_grid.is-tight{grid-template-columns:repeat(auto-fit,minmax(min(10rem,100%),1fr))}
.layout_grid.is-gap-small{gap:var(--space--xsmall)}
.layout_grid.is-gap-large{gap:var(--space--large)}

.layout_stack{display:flex;flex-direction:column;gap:var(--space--small)}
.layout_stack.is-gap-tiny{gap:var(--space--tiny)}
.layout_stack.is-gap-small{gap:var(--space--xsmall)}
.layout_stack.is-gap-large{gap:var(--space--large)}

.layout_row{display:flex;flex-wrap:wrap;align-items:center;gap:var(--space--xsmall)}
.layout_row.is-top{align-items:flex-start}
.layout_row.is-spread{justify-content:space-between}
.layout_row.is-nowrap{flex-wrap:nowrap}

/* ======================================================================
   6. CARD, PANEL, CHIP
   The three surfaces every screen ends up needing. A card is a thing; a
   panel is a region of a screen; a chip is a word about something.
   ====================================================================== */

.card_component{
  display:flex;flex-direction:column;gap:var(--space--xsmall);
  padding:var(--space--small);
  border:var(--border-main,1px) solid var(--rule);
  border-radius:var(--radius,0);
  background-color:var(--card);
}
.card_component.is-raised{box-shadow:var(--shadow,none)}
.card_component.is-flat{border-color:var(--rule-soft);box-shadow:none}
.card_header{display:flex;flex-wrap:wrap;align-items:baseline;justify-content:space-between;gap:var(--space--xxsmall)}
.card_body{display:flex;flex-direction:column;gap:var(--space--xxsmall)}
.card_footer{display:flex;flex-wrap:wrap;align-items:center;gap:var(--space--xxsmall);
  padding-top:var(--space--xsmall);border-top:1px solid var(--rule-soft)}

.panel_component{
  padding:var(--space--small);
  border:var(--border-main,1px) solid var(--rule);
  border-radius:var(--radius,0);
  background-color:var(--card);
}
.panel_component.is-raised{box-shadow:var(--shadow,none)}
.panel_component.is-deep{background-color:var(--nav);color:var(--color--text-on-deep);border-color:var(--rule-deep)}
.panel_component.is-quiet{background-color:var(--color--background-alt);border-color:var(--rule-soft)}

.chip{
  display:inline-flex;align-items:center;gap:var(--space--tiny);
  padding:0.125rem 0.5rem;
  border:1px solid currentColor;
  border-radius:var(--radius-sm,0);
  font-family:var(--cond,inherit);
  font-size:var(--text--tiny);
  font-weight:700;
  letter-spacing:var(--label-tracking,.09em);
  text-transform:uppercase;
  white-space:nowrap;
}
/* A report nobody has assessed gets no colour at all — outlined ink,
   unfilled. It has not earned one. */
.chip.is-open{color:var(--muted)}
.chip.is-serious{background-color:var(--seal);border-color:var(--seal);color:var(--on-seal)}
.chip.is-confirmed{background-color:var(--verify);border-color:var(--verify);color:var(--on-verify)}

/* ======================================================================
   7. SPACING UTILITIES
   Two classes together: a DIRECTION and a SIZE.

     <div class="margin-bottom margin-small">

   The direction class zeroes the three sides you did not name, so the pair
   can only ever set the one edge you asked for. That is why the zeroes are
   `!important` — they have to beat the size class, which sets all four.

   WHY THESE COME LAST, with the other utilities: a component sets its own
   margins, and a utility has to be able to overrule one. `heading-style-h2`
   sets `margin:0`, and written above this block it beat `margin-small` —
   which looked like a spacing class that silently did nothing.
   ====================================================================== */
.margin-top{margin-right:0 !important;margin-bottom:0 !important;margin-left:0 !important}
.margin-right{margin-top:0 !important;margin-bottom:0 !important;margin-left:0 !important}
.margin-bottom{margin-top:0 !important;margin-right:0 !important;margin-left:0 !important}
.margin-left{margin-top:0 !important;margin-right:0 !important;margin-bottom:0 !important}
.margin-horizontal{margin-top:0 !important;margin-bottom:0 !important}
.margin-vertical{margin-right:0 !important;margin-left:0 !important}

.padding-top{padding-right:0 !important;padding-bottom:0 !important;padding-left:0 !important}
.padding-right{padding-top:0 !important;padding-bottom:0 !important;padding-left:0 !important}
.padding-bottom{padding-top:0 !important;padding-right:0 !important;padding-left:0 !important}
.padding-left{padding-top:0 !important;padding-right:0 !important;padding-bottom:0 !important}
.padding-horizontal{padding-top:0 !important;padding-bottom:0 !important}
.padding-vertical{padding-right:0 !important;padding-left:0 !important}

.margin-0{margin:0rem !important}
.margin-tiny{margin:var(--space--tiny)}
.margin-xxsmall{margin:var(--space--xxsmall)}
.margin-xsmall{margin:var(--space--xsmall)}
.margin-small{margin:var(--space--small)}
.margin-medium{margin:var(--space--medium)}
.margin-large{margin:var(--space--large)}
.margin-xlarge{margin:var(--space--xlarge)}
.margin-xxlarge{margin:var(--space--xxlarge)}

.padding-0{padding:0rem !important}
.padding-tiny{padding:var(--space--tiny)}
.padding-xxsmall{padding:var(--space--xxsmall)}
.padding-xsmall{padding:var(--space--xsmall)}
.padding-small{padding:var(--space--small)}
.padding-medium{padding:var(--space--medium)}
.padding-large{padding:var(--space--large)}
.padding-xlarge{padding:var(--space--xlarge)}
.padding-xxlarge{padding:var(--space--xxlarge)}

/* An empty div that holds air open between two things, where neither of
   them owns the gap. Cheaper to read in the markup than a margin nobody
   can see, and it collapses to nothing when it is hidden on a phone. */
.spacer-tiny{width:100%;padding-top:var(--space--tiny)}
.spacer-xxsmall{width:100%;padding-top:var(--space--xxsmall)}
.spacer-xsmall{width:100%;padding-top:var(--space--xsmall)}
.spacer-small{width:100%;padding-top:var(--space--small)}
.spacer-medium{width:100%;padding-top:var(--space--medium)}
.spacer-large{width:100%;padding-top:var(--space--large)}
.spacer-xlarge{width:100%;padding-top:var(--space--xlarge)}
.spacer-xxlarge{width:100%;padding-top:var(--space--xxlarge)}

/* ======================================================================
   8. UTILITIES
   One decided value each, and they win over everything above because they
   are loaded last.
   ====================================================================== */

.hide{display:none !important}
@media screen and (max-width:61.9375rem){.hide-tablet{display:none !important}}
@media screen and (max-width:47.9375rem){.hide-mobile-landscape{display:none !important}}
@media screen and (max-width:29.9375rem){.hide-mobile{display:none !important}}
@media screen and (min-width:48rem){.show-mobile-only{display:none !important}}

/* Off the screen but not out of the page: still read aloud, still reachable
   by a keyboard. For a label a sighted reader gets from context and a
   screen reader would otherwise never hear. */
.hide-visually{
  position:absolute !important;width:1px;height:1px;
  padding:0;margin:-1px;overflow:hidden;white-space:nowrap;
  clip:rect(0 0 0 0);clip-path:inset(50%);border:0;
}

.align-center{margin-left:auto;margin-right:auto}
.max-width-xsmall{width:100%;max-width:20rem}
.max-width-small{width:100%;max-width:26rem}
.max-width-medium{width:100%;max-width:36rem}
.max-width-large{width:100%;max-width:48rem}
.max-width-full{width:100%;max-width:none}

.overflow-hidden{overflow:hidden}
.overflow-auto{overflow:auto}
.position-relative{position:relative}
.z-index-1{position:relative;z-index:1}
.z-index-2{position:relative;z-index:2}
.pointer-events-none{pointer-events:none}
.pointer-events-auto{pointer-events:auto}
.display-none{display:none}
.display-block{display:block}
.display-flex{display:flex}
.display-inlineflex{display:inline-flex}
.width-full{width:100%}
.flex-1{flex:1 1 auto;min-width:0}

/* A rule across the page, drawn in the palette's hairline. */
.divider{height:1px;width:100%;background-color:var(--rule-soft);border:0;margin:0}

/* Somebody has asked their system not to animate things. Honour it: the
   press on a button is motion, and so is anything added later. */
@media (prefers-reduced-motion:reduce){
  .button:active{transform:none}
}

/* ======================================================================
   7. MODAL
   A dialog over the page. `.on` on the overlay opens it: every script in
   this app says so, and there are a great many of them.
   ====================================================================== */

.modal_overlay{display:none;position:fixed;inset:0;background:color-mix(in srgb,var(--ink) 55%,transparent);z-index:100;
  align-items:center;justify-content:center;padding:16px}
.modal_overlay.on{display:flex}
.modal_component{background:var(--color--surface);max-width:480px;width:100%;max-height:88vh;overflow:auto;padding:22px}
.modal_title{font-family:var(--cond);font-weight:700;font-size:18px;margin:0 0 12px}
.modal_component .modal_field{margin:0 0 12px}
.modal_component .modal_actions{display:flex;justify-content:flex-end;gap:8px;margin-top:16px}
.modal_component .modal_actions.split{justify-content:space-between}

/* ======================================================================
   8. TABS
   Sub-navigation inside one pane. Show and hide only: it changes no URL and
   pushes no history entry, because every pane is in the DOM from the first
   byte and popstate must never route while the site is gated.
   ====================================================================== */

.tabs_menu{display:flex;gap:6px;flex-wrap:wrap;margin:0 0 20px;
  border-bottom:1px solid var(--rule);padding-bottom:0}
.tabs_button{font-family:var(--cond);font-weight:700;font-size:13px;
  letter-spacing:.06em;text-transform:uppercase;background:none;border:0;
  border-bottom:3px solid transparent;color:var(--muted);cursor:pointer;
  padding:9px 12px;margin-bottom:-1px}
.tabs_button:hover{color:var(--ink)}
/* aria-current carries the state, so the styling cannot drift from what a
   screen reader is told. */
.tabs_button[aria-current="true"]{color:var(--ink);border-bottom-color:var(--act)}
.tabs_button:focus-visible{outline:2px solid var(--act);outline-offset:-2px}
@media(max-width:560px){
  /* Scrolls sideways rather than wrapping to three rows on a phone. */
  .tabs_menu{flex-wrap:nowrap;overflow-x:auto;scrollbar-width:none}
  .tabs_menu::-webkit-scrollbar{display:none}
  .tabs_button{white-space:nowrap}
}

/* ======================================================================
   9. FILTER BAR, SEARCH BAR, EMPTY STATE
   ====================================================================== */

.filter_bar{display:flex;gap:8px;align-items:center;margin:0 0 12px;flex-wrap:wrap}
.filter_bar .form_select{width:auto;padding:8px 30px 8px 10px;font-size:14px}
/* search boxes in filter bars */
.filter_bar .form_input[type=search]{width:auto;flex:1 1 200px;min-width:170px;max-width:360px;
  padding:8px 10px;font-size:14px}
/* One compact toolbar shared by the report board and the moderator queue:
   search, a single Filter button, and nothing else competing for space. */
.search_bar{display:flex;gap:8px;align-items:center;flex-wrap:wrap;margin:0 0 9px}
.search_bar .form_input{flex:1 1 220px;min-width:150px;max-width:none;width:auto;
  padding:9px 11px;font-size:14px}
.search_bar .button{flex:0 0 auto}

.empty_component{background:var(--card);border:1px dashed var(--rule);padding:40px 20px;text-align:center;color:var(--muted);font-size:14.5px}
