/* =============================================================================
   Opsy website — shared styles, loaded by every page.

   Flat plain CSS on the kit's tokens (kit/tokens.css): no nesting and no SCSS,
   so this file drops into the site repo's PostCSS pipeline unchanged. Every
   class wears the `op-` prefix to stay clear of that repo's legacy names
   (.button, .hero, .footer) and of Tailwind's utilities.

   Type comes from the kit's classes (kit/typography.css); the two styles its
   scale does not reach are defined below.
   Spec: docs/specs/2026-10-04-website-home-style-spike.md
   ========================================================================== */

/* --- Page ------------------------------------------------------------------ */
/* The kit's --surface-page is the app's grey; the site sits on plain white. */
.op-page {
  margin: 0;
  background: var(--white);
  /* The page's vertical rhythm, said once. The kit's spacing scale stops at
     40px, so the gaps larger than that are these three named steps, each a
     multiple of a kit step:
       near     a block that belongs to the one above it (the numbers under
                the hero): 96px
       section  a new section starts: 128px
       intro    a section's heading to what it heads: 48px
     The gap between two sections binds one of them and never its own
     multiple; the padding inside a coloured block (the band, a panel, the
     footer) is that block's own. They sit on .op-page and not on :root, so
     their narrow values (Narrow, below) also reach a page shown inside a
     container -- the flow tuner's stage, where a media query becomes a
     container query and :root is out of reach. */
  --op-space-near: calc(var(--space-8) * 3);
  --op-space-section: calc(var(--space-8) * 4);
  --op-space-intro: calc(var(--space-6) * 2);
  /* The header's height on a wide screen, said once: its bar takes it
     (Header, below), and a page that pins something under the header, or
     stops a jump clear of it, reads it (css/process.css). */
  --op-header-h: 74px;
}

/* Zero-specificity defaults: :where() weighs nothing, so any class below
   overrides these without a specificity fight. */
:where(.op-page) :where(h1, h2, h3, p, ul, ol, dl, dd) {
  margin: 0;
}
:where(.op-page) :where(ul, ol) {
  padding: 0;
  list-style: none;
}
:where(.op-page) :where(img, svg) {
  display: block;
  max-width: 100%;
}
:where(.op-page) :where(h1, h2, h3) {
  /* A primitive: the blueprint's deep-teal ink has no honest semantic alias
     (--text-primary is the app's near-black). */
  color: var(--genoa-950);
  text-wrap: balance;
}
/* The kit's focus ring (foundations/_focus.scss), bound to the same tokens. */
:where(.op-page) :where(a, button, [tabindex]):focus-visible {
  outline: var(--focus-ring-width) solid var(--focus-ring-color);
  outline-offset: var(--focus-ring-offset);
}

.op-wrap {
  width: min(100% - var(--space-6) * 2, 1180px);
  margin-inline: auto;
}

/* A phrase that moves to the next line as one piece -- a heading breaks at its
   comma instead of wherever the line happens to fill. Still wraps inside when
   the column is narrower than the phrase. */
.op-keep {
  display: inline-block;
}

/* --- Type the kit's scale does not reach ----------------------------------- */
/* The kit tops out at .heading-h1, 48px. A marketing headline needs more.
   The size runs in a straight line from 32px on a 390px phone to 68px at
   1280px and holds there -- two named sizes, so each can be tuned on its own
   (a bare 5.2vw left the larger one out of reach below 1300px). The 32px
   floor lets the headline's longest word, "försäkringsmedicin", fit a 360px
   phone column whole instead of being hyphenated. */
.op-display {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(32px, calc(32px + 36 * (100vw - 390px) / 890), 68px);
  /* Between the kit's tight (100%) and snug (120%): two lines of display type
     carrying Swedish diacritics. */
  line-height: 1.08;
  letter-spacing: -0.025em;
}

/* A section's label: the small line above a section's heading, or a panel's
   own title. That one job and no other -- a column or list heading takes a
   kit class -- because it stops reading as a signal once it is everywhere.
   The kit's .eyebrow is 10px, sized for dense app chrome. Semibold, the
   user's ruling of 2026-10-06: it was medium. */
.op-eyebrow {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 12px;
  line-height: var(--lh-snug);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--brand-primary);
}

/* --- Button — the kit's Button (components/Button), in plain CSS ----------- */
.op-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid transparent;
  border-radius: var(--radius-xs);
  font-family: var(--font-display);
  font-weight: 600;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  transition:
    background-color var(--motion-fast) var(--ease-standard),
    border-color var(--motion-fast) var(--ease-standard),
    color var(--motion-fast) var(--ease-standard);
}
.op-btn--md {
  height: 40px;
  padding: var(--space-2) var(--space-4);
  font-size: 14px;
  line-height: 14px;
}
.op-btn--lg {
  height: 48px;
  padding: var(--space-3) var(--space-5);
  font-size: 16px;
  line-height: 16px;
}
.op-btn--solid {
  background: var(--brand-action);
  color: var(--white);
}
.op-btn--solid:hover {
  background: var(--brand-action-hover);
}
.op-btn--solid:active {
  background: var(--brand-action-pressed);
}
.op-btn--outline {
  background: var(--surface-card);
  border-color: var(--border-default);
  color: var(--brand-action);
}
.op-btn--outline:hover {
  background: var(--brand-bg);
  border-color: var(--genoa-300);
}
.op-btn--outline:active {
  background: var(--brand-bg-hover);
  border-color: var(--genoa-600);
}
/* The kit's ghost: no fill, and the action's teal let through at a share on
   hover and press, so the wash takes on whatever ground the button lies on. */
.op-btn--ghost {
  background: transparent;
  color: var(--brand-action);
}
.op-btn--ghost:hover {
  background: color-mix(in srgb, var(--brand-action) 20%, transparent);
}
.op-btn--ghost:active {
  background: color-mix(in srgb, var(--brand-action) 30%, transparent);
}

/* --- Text link — the kit Button's `link` variant --------------------------- */
/* Only the label is underlined; the arrow beside it stays bare. */
.op-link {
  font-family: var(--font-body);
  font-weight: 500;
  font-size: 16px;
  color: var(--text-link);
  text-decoration: none;
  transition: color var(--motion-fast) var(--ease-standard);
}
.op-link__label {
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 2px;
}
.op-link:hover {
  color: var(--brand-action-hover);
}
.op-link:hover .op-link__label {
  text-decoration-thickness: 2px;
}
.op-link:active {
  color: var(--brand-action-pressed);
}

/* --- Tag -------------------------------------------------------------------- */
/* A plain label on a fill: the kinds of case on the OpsyOne & OpsyGO page, who
   does a step on Så fungerar det. Filled and without an outline, on an 8px
   corner: an outlined pill is how a button is drawn, and a tag does nothing.
   Its ground and ink are the number highlight's (css/home.css,
   .op-stat__value), the user's ruling: a mint one step deeper than the
   brand's own -- a primitive, the kit's only alias for it names a hover --
   and the brand's deep teal on it. A tag is a label, not text that is read,
   so it names its ink. Its type is the markup's (body-sm). (They were the
   body ink on the brand's faintest mint first.) */
.op-kind {
  padding: var(--space-1) var(--space-3);
  border-radius: var(--radius-sm);
  background: var(--genoa-100);
  color: var(--brand-primary);
}

/* --- Header ----------------------------------------------------------------- */
/* The brief's header (spec, Rev 1): a white strip, the wordmark, the menu,
   and at the far end the login link and the action. The nav sits in the
   middle of the room between the two (Rev 2); the brief has it on the left.
   The menu is the brief's without Hem and with the live site's Investerare
   (docs/specs/2026-10-05-website-port-home-page.md). No hairline
   under the strip (Rev 5; the brief draws one): once the page scrolls, the
   frosted fill is what sets the strip apart from the content passing under it.
   The strip is white and not brand-tinted because the current page's pill is
   --brand-bg -- on a tinted strip it would not show. */
.op-header {
  position: sticky;
  top: 0;
  z-index: var(--z-topbar);
  background: color-mix(in srgb, var(--white) 88%, transparent);
  -webkit-backdrop-filter: blur(12px);
  backdrop-filter: blur(12px);
}
.op-header__bar {
  display: flex;
  align-items: center;
  gap: var(--space-6);
  min-height: var(--op-header-h);
}
.op-header__brand {
  flex: none;
  display: inline-flex;
  border-radius: var(--radius-xs);
}
.op-header__brand img {
  height: 26px;
  width: auto;
}
/* Takes the room between wordmark and actions. On a screen too narrow for
   the row it is the menu's list instead, opened by the menu button (Narrow,
   The menu as a list) -- which is why it is a popover in the markup, and why
   the box a browser gives a popover is undone here: where the row fits, the
   nav is never opened as one and stands in the row like any element. Where a
   browser knows no popovers the row scrolls sideways when its links outgrow
   it; a scrolling box clips its children's focus ring, so the nav is padded
   by the ring's reach. */
.op-header__nav {
  position: static;
  inset: auto;
  flex: 1;
  width: auto;
  min-width: 0;
  height: auto;
  display: flex;
  align-items: center;
  gap: var(--space-1);
  margin: 0;
  padding: var(--space-1);
  overflow-x: auto;
  scrollbar-width: none;
  border: 0;
  background: none;
  color: inherit;
}
/* Centred by auto margins, not justify-content: when the links overflow, the
   margins give way to zero and the first link stays reachable by scrolling --
   centred overflow would push it out of reach on the left. The margins are
   on two empty boxes at the row's ends and not on its first and last link:
   the last entry in the markup is the list's own Logga in, absent here. */
.op-header__nav::before,
.op-header__nav::after {
  content: '';
}
.op-header__nav::before {
  margin-left: auto;
}
.op-header__nav::after {
  margin-right: auto;
}
/* The list's own Logga in: at the list's end on a phone, where the one in
   the actions group has left the row (Narrow, The menu as a list). There it
   is the kit's outline button, the secondary one, as Home's second action
   is -- a menu link at first, and the user's ruling on seeing that (spec,
   Rev 2). */
.op-nav__login {
  display: none;
}
/* The login link, the action and the menu button, a group that stays
   together at the row's far end. */
.op-header__actions {
  flex: none;
  display: flex;
  align-items: center;
  gap: var(--space-2);
}
/* The menu button: the dialog's close button again, a ghost button made
   square. Absent where the menu's row fits, and where a browser knows no
   popovers. It holds two marks, the three lines and the cross; which one
   shows is said with the list's rules (Narrow). Its name, Meny, is new copy
   the user confirmed (spec, decision 5). */
.op-header__toggle {
  display: none;
  width: 40px;
  padding: 0;
}
.op-header__toggle .op-ico + .op-ico {
  display: none;
}
.op-navlink {
  flex: none;
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-sm);
  font-family: var(--font-display);
  font-weight: 500;
  font-size: 14px; /* the kit's label size; the brief has 14.5px */
  line-height: var(--lh-relaxed);
  letter-spacing: -0.01em;
  /* The body ink, named outright: a link does not inherit it -- the browser's
     own stylesheet gives links a colour. */
  color: var(--text-primary);
  text-decoration: none;
  white-space: nowrap;
  transition: background-color var(--motion-fast) var(--ease-standard);
}
/* The page you are on. Styled off aria-current, so what is shown and what a
   screen reader announces cannot drift apart. */
.op-navlink[aria-current='page'],
.op-navlink.is-within {
  background: var(--brand-bg);
  font-weight: 600;
  color: var(--brand-primary);
}
.op-navlink:hover {
  background: var(--brand-bg-hover);
}

/* A menu entry that opens a panel of links: Investerare and the pages under
   it (docs/specs/2026-10-06-website-investerare-page.md). A button that shows
   a list of links -- the disclosure pattern, not a menu of commands. The
   wrapper keeps button and panel together as one child of the row, so the
   centring margin (above) lands on it and not on the hidden panel. */
.op-navmenu {
  flex: none;
  display: flex;
}
/* The button is drawn as a menu link. A button brings a border, a fill, a
   margin and a cursor of its own; a link has none of them. When its panel
   holds the page shown it takes the current page's pill (.is-within, above):
   the mark a screen reader announces is on the entry inside. */
.op-navlink--menu {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  margin: 0;
  border: 0;
  background: none;
  cursor: pointer;
}
/* The sprite's chevron points right: turned down, and up while the panel is
   open. Open is read off aria-expanded, which js/menu.js keeps; the hover's
   wash stays for as long as the panel is open. */
.op-navlink .op-ico {
  width: 16px;
  height: 16px;
  rotate: 90deg;
  transition: rotate var(--motion-fast) var(--ease-standard);
}
.op-navlink--menu[aria-expanded='true'] {
  background: var(--brand-bg-hover);
}
.op-navlink--menu[aria-expanded='true'] .op-ico {
  rotate: -90deg;
}
/* The panel is the kit Menu's: white, a fine border, an 8px corner, the small
   shadow, 4px inside, 8px under its button, right edges in line (the kit's
   align="end", for a button near a right edge), at least the button's width.
   It is a popover: the browser draws it above the page, outside the menu row
   -- a scrolling box cuts off whatever hangs out of it -- and hides it while
   closed, which is why no display is named here. A popover does not know
   where its button is, so js/menu.js measures the button and hands over its
   bottom edge, its distance from the window's right edge and its width; the
   places are worked out here. Without the script the panel opens under the
   header at the page's edge. Its entries are menu links, stacked. */
.op-menu {
  position: fixed;
  inset: auto;
  top: calc(var(--op-menu-under, var(--op-header-h)) + var(--space-2));
  right: max(var(--space-4), var(--op-menu-right, var(--space-6)));
  min-width: var(--op-menu-width, 0px);
  margin: 0;
  padding: var(--space-1);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-sm);
  background: var(--surface-card);
  box-shadow: var(--shadow-sm);
}
.op-menu .op-navlink {
  display: block;
}
/* A browser too old for popovers would show the panel all the time. There the
   button is absent and the links stand in the row. */
@supports not selector(:popover-open) {
  .op-navlink--menu {
    display: none;
  }
  .op-menu {
    position: static;
    display: flex;
    gap: var(--space-1);
    min-width: 0;
    padding: 0;
    border: 0;
    background: none;
    box-shadow: none;
  }
}

/* --- A bare page ------------------------------------------------------------ */
/* A page that is one embedded page from another site (Investerare: Spotlight
   Stock Market's page for the share), and has no footer -- the frame's
   switch, opBare. Another site's page cannot report its height, so the frame
   cannot grow to fit it. The page is instead a column exactly the window's
   height: the header takes what it needs at any width, the frame takes the
   room left and scrolls inside itself, and there is one scrollbar. The frame
   is never lower than 500px; in a window shorter than that the page scrolls. */
.op-page--bare {
  display: flex;
  flex-direction: column;
  min-height: 100vh; /* for a browser without the unit below */
  min-height: 100dvh;
}
.op-page--bare > main {
  flex: 1;
  display: flex;
  flex-direction: column;
}
.op-embed {
  flex: 1;
  width: 100%;
  min-height: 500px;
  border: 0;
}

/* --- Footer ----------------------------------------------------------------- */
/* A dark footer, as in the brief, on the deepest step of the brand's teal --
   one below the trust band's, where the brief uses the band's own. A
   primitive: it is the page's heading ink (above) and has no semantic alias.
   Its lights are written as the band's are, white let through at a share. No
   line above it: the ground marks the edge. */
.op-footer {
  padding-block: calc(var(--space-8) * 2) var(--space-10);
  background: var(--genoa-950);
  color: color-mix(in srgb, var(--white) 86%, transparent);
}
.op-footer__grid {
  display: grid;
  grid-template-columns: 1.6fr 1fr 1fr 1.2fr;
  gap: var(--space-10);
}
.op-footer__col {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-2);
}
/* The kit has one wordmark and it is dark; the brief turns it white this way. */
.op-footer__col img {
  height: 28px;
  width: auto;
  margin-bottom: var(--space-3);
  filter: brightness(0) invert(1);
}
/* A column's heading: a plain small heading (the kit's label-md), and not the
   section label, which names sections and nothing else. */
.op-footer__title {
  color: var(--white);
}
/* Plain text under a heading starts where a link under one does: links are
   padded to a 33px row, and the three columns' first lines should share a line. */
.op-footer__title + p {
  padding-top: var(--space-1-5);
}
.op-footer__links {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
}
/* Padded to a 33px row: the audience's click targets stay at 32px or more. */
.op-footlink {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding-block: var(--space-1-5);
  color: inherit;
  text-decoration: none;
}
.op-footlink:hover {
  color: var(--white);
  text-decoration: underline;
}
/* The kit's ring colour is chosen for light surfaces; on this ground it is white. */
.op-footer :where(a):focus-visible {
  outline-color: var(--white);
}
.op-footer__legal {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: var(--space-4);
  margin-top: var(--space-10);
  padding-top: var(--space-6);
  border-top: 1px solid color-mix(in srgb, var(--white) 22%, transparent);
  color: color-mix(in srgb, var(--white) 72%, transparent);
}

/* --- Icons ------------------------------------------------------------------ */
/* An icon is a stencil: a flat file is its mask, and the colour of the text
   around it shows through. So it follows a hover, a status colour or the
   footer's white as a line drawing would, from one file. The masks are
   art/icons.css, exported from the masters in website/drawings/: each icon's
   own class there (.op-ico--menu) names its mask, at the size it is shown.
   Without that file nothing shows, where an unmasked box would be a square. */
.op-ico {
  flex: none;
  display: block;
  width: 20px;
  height: 20px;
  background-color: currentColor;
  mask: var(--op-ico, linear-gradient(transparent, transparent)) center / contain no-repeat;
  print-color-adjust: exact;
}
/* Where the reader's own colours replace the page's, a background is the
   first thing dropped: the stencil keeps its fill, in the system's colour for
   the text it sits in. */
@media (forced-colors: active) {
  .op-ico {
    forced-color-adjust: none;
    background-color: CanvasText;
  }
  :where(button) .op-ico {
    background-color: ButtonText;
  }
  :where(a) .op-ico {
    background-color: LinkText;
  }
}

/* --- Dialog — the kit's Modal (components/Modal), in plain CSS -------------- */
/* The browser's own <dialog>, opened by js/booking.js with showModal(): it
   keeps focus inside, closes on Escape, hands focus back to the button that
   opened it and sits above the whole page, the header included -- so there is
   no z-index here. The panel is the kit's: white, a 16px corner, the shadow
   scale's step for modals. Its width and padding are the brief's proportions,
   520 and 32; the app's own modal is 480 and 24.
   The scrim is the panel's second shadow, spread past any screen, and not
   ::backdrop: until 2024 a backdrop could not read a custom property, and a
   token is the only way a colour is written here. The backdrop is still
   there, clear, and takes the click outside.
   Spec: docs/specs/2026-10-06-website-booking-dialog.md */
.op-dialog {
  box-sizing: border-box;
  width: min(100% - var(--space-4) * 2, 520px);
  max-width: none;
  /* A screen shorter than the form: the panel scrolls, and never touches the
     screen's edge. The first line is for a browser without dvh. */
  max-height: calc(100vh - var(--space-4) * 2);
  max-height: calc(100dvh - var(--space-4) * 2);
  padding: var(--space-8);
  overflow-y: auto;
  border: none;
  border-radius: var(--radius-lg);
  background: var(--surface-card);
  box-shadow: var(--shadow-lg), 0 0 0 100vmax var(--overlay-scrim);
  color: var(--text-primary);
}
.op-dialog::backdrop {
  background: transparent;
}
/* A part the script has put away. Said outright: a class that sets `display`
   outweighs the browser's own rule for the hidden attribute. */
.op-dialog [hidden] {
  display: none;
}
/* The page behind stays still while the dialog is open. The gutter keeps the
   room a classic scrollbar took, so the page does not jump sideways. */
:root:has(.op-dialog[open]) {
  overflow: hidden;
  scrollbar-gutter: stable;
}
/* The kit Modal's arrival: a short rise out of nothing. The scrim, being the
   panel's shadow, fades in with it. */
@media (prefers-reduced-motion: no-preference) {
  .op-dialog[open] {
    animation: op-dialog-in var(--motion-base) var(--ease-out);
  }
}
@keyframes op-dialog-in {
  from {
    opacity: 0;
    translate: 0 var(--space-2);
  }
}
/* The close button: a ghost button made square, in the panel's top corner.
   Its box is 40px for the hand; pulled out by the 10px its cross sits inside
   it, so the cross and not the box lines up with the fields' right edge. */
.op-dialog__close {
  float: right;
  width: 40px;
  padding: 0;
  margin: calc(var(--space-1-5) * -1) calc(var(--space-2-5) * -1) 0 var(--space-4);
}
/* The lead under the title: the secondary ink's first job on this site. It
   starts below the close button, which the title alone flows beside. */
.op-dialog__lead {
  clear: right;
  margin-top: var(--space-2);
  color: var(--text-secondary);
}
/* 12px between the fields, and a message box of three lines (the template's
   `rows`): the demo form is 714px high, and its send button is in view in a
   window 640px high. At the brief's 16px and four lines it was 758, the
   button below the panel's edge on most laptops. The user's pick, by eye. */
.op-dialog__form {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  margin-top: var(--space-6);
}
.op-dialog__send {
  width: 100%;
  margin-top: var(--space-2);
}
/* The lines under the send button. A link inside one is part of its sentence
   and takes the sentence's size. Its padding is for the hand, as the footer
   links': the word is 17px high and a click target here is 32px or more. On a
   link inside a line, padding above and below moves nothing. */
.op-dialog__notes {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}
.op-dialog__notes .op-link {
  padding-block: var(--space-2);
  font-size: inherit;
}
/* The thank-you takes the form's place and is where focus goes, by script:
   no ring, as on the kit Modal's panel. */
.op-dialog__thanks {
  margin-top: var(--space-6);
  outline: none;
}

/* --- Field — the kit's field (foundations/_field.scss), in plain CSS -------- */
/* A label above its control and an error line under it. The control is the
   kit's: white, the default outline, a 4px corner; the outline a step darker
   on hover, a soft ring on focus, the danger pair when its value is wrong.
   It keeps that focus treatment, as in the kit, and not the outline ring that
   links and buttons have. Larger than the app's, which is 40px high with 14px
   text: 48px as the large button beside it, and 16px text -- under 16px a
   phone zooms the page in when a field is tapped. */
.op-field {
  display: flex;
  flex-direction: column;
  gap: var(--space-1-5);
}
/* The asterisk after a required field's label. For the eye: the control's own
   `required` says it to a screen reader. */
.op-field__mark {
  margin-inline-start: 2px; /* a hair, below the spacing scale, as in the kit */
  color: var(--status-danger);
}
.op-field__control {
  box-sizing: border-box;
  width: 100%;
  height: 48px;
  padding: 0 var(--space-3);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-xs);
  background: var(--surface-card);
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 16px;
  line-height: var(--lh-snug);
  color: var(--text-primary);
  transition:
    border-color var(--motion-fast) var(--ease-standard),
    box-shadow var(--motion-fast) var(--ease-standard);
}
/* A field of several lines: it grows downwards only, and never below one line's height. */
.op-field__control--area {
  display: block;
  height: auto;
  min-height: 48px;
  padding-block: var(--space-3);
  line-height: var(--lh-relaxed);
  resize: vertical;
}
.op-field__control::placeholder {
  color: var(--text-placeholder);
  opacity: 1; /* Firefox dims a placeholder by itself */
}
.op-field__control:hover {
  border-color: var(--border-focus);
}
/* The ring is a primitive in the kit too: a soft grey with no semantic alias. */
.op-field__control:focus {
  outline: none;
  border-color: var(--border-focus);
  box-shadow: 0 0 0 2px var(--submarine-100);
}
/* After hover and focus on purpose: a wrong value keeps its red outline
   whatever the pointer does. */
.op-field__control[aria-invalid='true'] {
  border-color: var(--status-danger);
}
.op-field__control[aria-invalid='true']:focus {
  box-shadow: 0 0 0 2px var(--status-danger-bg);
}
.op-field__error {
  color: var(--status-danger-text);
}

/* --- Notice — the kit's InlineBanner (components/InlineBanner), in plain CSS - */
/* A status message: a tint, an outline and a mark, each status with its own
   family of three. The mark and the first line take the status ink; a line
   under it is read as text and keeps the body ink. */
.op-notice {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  padding: var(--space-4);
  border: 1px solid;
  border-radius: var(--radius-sm);
}
.op-notice--success {
  border-color: var(--status-success-border);
  background: var(--status-success-bg);
  color: var(--status-success-text);
}
.op-notice--danger {
  border-color: var(--status-danger-border);
  background: var(--status-danger-bg);
  color: var(--status-danger-text);
}
/* The 20px mark, centred on a first line 24px high. */
.op-notice .op-ico {
  margin-top: 2px;
}
.op-notice__text {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  min-width: 0;
}
.op-notice__more {
  color: var(--text-primary);
}

/* --- Narrow ----------------------------------------------------------------- */
/* The pages stack and no more. The header, the headings and what a finger
   presses have their own rulings, from the phone review of 2026-10-07:
   docs/specs/2026-10-07-website-phone-menu-and-phone-fixes.md */
/* The rhythm's narrow values, 72px and 80px: the wide ones are set for a wide
   screen. A heading stays 48px above what it heads at every width. */
@media (max-width: 960px) {
  .op-page {
    --op-space-near: calc(var(--space-9) * 2);
    --op-space-section: calc(var(--space-10) * 2);
  }
}

/* The menu as a list. Below 1240px the menu's row no longer fits beside the
   wordmark and the actions -- it needs 1221px, and a classic scrollbar takes
   some 17px of the window -- so the nav is closed and the menu button opens
   it. It is a popover: the browser draws it above the page, closes it on
   Escape or a tap outside it, and hands focus back to the button. Open, it
   fills the screen from the header's bottom edge down: js/menu.js hands that
   edge over, and the header's named height stands in where the header is
   pinned and the script has not run. All of this only where the browser
   knows popovers; the others keep the row (the block after this one). */
@supports selector(:popover-open) {
  @media (max-width: 1240px) {
    .op-header__brand {
      margin-right: auto;
    }
    .op-header__toggle {
      display: inline-flex;
    }
    /* The cross while the list is open: read off the list itself, so the
       mark is right without the script. */
    .op-header:has(.op-header__nav:popover-open) .op-header__toggle .op-ico {
      display: none;
    }
    .op-header:has(.op-header__nav:popover-open) .op-header__toggle .op-ico + .op-ico {
      display: block;
    }
    /* The browser hides a closed popover; the row's own `display` would show it. */
    .op-header__nav[popover]:not(:popover-open) {
      display: none;
    }
    .op-header__nav[popover]:popover-open {
      position: fixed;
      inset: var(--op-nav-under, var(--op-header-h)) 0 0;
      flex-direction: column;
      align-items: stretch;
      padding: var(--space-3);
      overflow: hidden auto;
      overscroll-behavior: contain;
      scrollbar-width: auto;
      background: var(--white);
    }
    /* The row's centring boxes have no place in a list. */
    .op-header__nav:popover-open::before,
    .op-header__nav:popover-open::after {
      content: none;
    }
    /* An entry: a menu link at the kit's subhead size, the flow steps' own,
       in a 48px row -- a finger's target with room to spare. Its side padding
       is the row's, so an entry's text starts on the wordmark's left edge. */
    .op-header__nav:popover-open .op-navlink {
      display: flex;
      align-items: center;
      min-height: 48px;
      padding-block: 0;
      font-size: 18px;
      line-height: var(--lh-snug);
    }
    /* Investerare's pages stand under it, always shown, as in the live site's
       own hamburger: the button that opens them in the row is absent, and
       their panel is a plain list in place. One list: its pages start on the
       same edge as every entry -- set in at first, and the user's ruling on
       seeing that (spec, Rev 2). */
    .op-header__nav:popover-open .op-navmenu {
      display: block;
    }
    .op-header__nav:popover-open .op-navlink--menu {
      display: none;
    }
    .op-header__nav:popover-open .op-menu {
      position: static;
      display: flex;
      flex-direction: column;
      gap: var(--space-1);
      width: auto;
      min-width: 0;
      padding: 0;
      border: 0;
      background: none;
      box-shadow: none;
    }
    /* The page behind stays still while the list is open, as behind the dialog. */
    :root:has(.op-header__nav:popover-open) {
      overflow: hidden;
      scrollbar-gutter: stable;
    }
  }
  /* One pinned row of 64px on a phone, 12px above and below the 40px buttons.
     The named height takes the value, so the bar and every offset that reads
     it -- a jump to a person, a report's cover -- follow. */
  @media (max-width: 720px) {
    .op-page {
      --op-header-h: 64px;
    }
  }
  /* On a phone Logga in leaves the row, which then holds the wordmark, the
     action and the menu button down to 320px, and stands at the list's end:
     as wide as the list, as Home's two actions are on a phone, and a step
     clear of the entries above it. */
  @media (max-width: 480px) {
    .op-header__bar {
      gap: var(--space-3);
    }
    .op-header__login {
      display: none;
    }
    .op-header__nav:popover-open .op-nav__login {
      display: inline-flex;
      margin-top: var(--space-3);
    }
  }
}
/* A browser that knows no popovers (Safari before 17) has no menu button and
   keeps the header it had: wordmark and actions share the first row, the nav
   takes the second and scrolls sideways, as the brief's does. */
@supports not selector(:popover-open) {
  @media (max-width: 720px) {
    .op-header__bar {
      flex-wrap: wrap;
      row-gap: 0;
      min-height: 0;
      padding-block: var(--space-3) var(--space-1);
    }
    .op-header__brand {
      margin-right: auto;
    }
    .op-header__nav {
      order: 1;
      flex: 0 0 100%;
    }
  }
}
@media (max-width: 720px) {
  .op-footer__grid {
    grid-template-columns: 1fr 1fr;
  }
}
/* On a phone each of the kit's headings takes the next kit size down: 48 to
   32, 32 to 24, 24 to 20. At their wide sizes a page's title, which is 32px
   on a phone (.op-display), was no larger than its section titles and smaller
   than a product's name. A rule on the classes, so a number set in one steps
   with it; the kit itself is untouched. The user's ruling (spec, decision 6);
   the one exemption, the row titles of a list, is in css/news.css. */
@media (max-width: 560px) {
  :where(.op-page) .heading-h1 {
    font-size: 32px;
  }
  :where(.op-page) .heading-h2 {
    font-size: 24px;
  }
  :where(.op-page) .heading-h3 {
    font-size: 20px;
  }
}
@media (max-width: 480px) {
  .op-footer__grid {
    grid-template-columns: 1fr;
  }
  /* On a phone the fields get the room the panel's wide padding took. */
  .op-dialog {
    padding: var(--space-6);
  }
  /* A word wider than a phone's column breaks rather than overflow it. No
     hyphens: a heading's lines are evened (text-wrap, above), and with
     hyphens on the browser split a long word to even them although it fit
     whole -- "Frågeställ-ningen förbereds", seen in the pass of 2026-10-07.
     At a phone's sizes no heading's word is wider than a 360px phone's
     column, so nothing needs one; on a 320px screen the titles' longest
     word, "försäkringsmedicin", breaks without. The user's ruling (spec
     docs/specs/2026-10-07-website-phone-menu-and-phone-fixes.md, Rev 1);
     a soft hyphen written into a title, as the news titles have, still
     works. */
  :where(.op-page) :where(h1, h2, h3) {
    overflow-wrap: anywhere;
  }
}
/* Under a finger. A screen with no hover and a coarse pointer is a touch
   screen -- the test js/booking.js makes -- and there a link in the footer is
   44px high, where a mouse has the 33px row. Plain text under a column's
   heading starts where a link's text now does. The user's ruling (spec,
   decision 8); the AI switch and Home's text links are in their own files. */
@media (hover: none) and (pointer: coarse) {
  .op-footlink {
    min-height: 44px;
  }
  .op-footer__title + p {
    padding-top: var(--space-3);
  }
}
