/* ============================================================================
   BesiktaBygget — design tokens
   ----------------------------------------------------------------------------
   The truth block below is the brand palette: navy and graphite on light paper
   with ONE restrained signal accent, which is §4 of the brief read literally.
   The alias block after it remaps the token names the ported admin stylesheet
   still references, BY ROLE rather than by hue — admin.css resolves ~520
   references across 2 200 lines, and aliasing is what lets the whole backoffice
   re-skin from this one file instead of a rewrite.

   New CSS should reference the brand tokens directly. The aliases exist to
   avoid touching admin.css, not as a second vocabulary to build on.
   ========================================================================== */

/* ── Fonts ──────────────────────────────────────────────────────────────────
   IBM Plex Sans, self-hosted rather than loaded from Google: the app ships as
   one binary with everything embedded, and a Swedish site that sends every
   visitor's IP to a third party on first paint is a GDPR liability with no
   upside.

   ONE file per subset, not one per weight. Google serves Plex as a VARIABLE
   font now — the 400, 500, 600 and 700 URLs all return the same bytes — so
   shipping four copies would be four identical 40 KB downloads. The weight
   range below is what lets the browser synthesise every weight we use from the
   single file.

   latin covers Swedish (å ä ö); latin-ext is listed so imported names with
   other diacritics still render. font-display: swap — text must be readable
   before the font arrives. */
@font-face {
  font-family: 'IBM Plex Sans'; font-style: normal; font-weight: 100 700;
  font-stretch: 100%; font-display: swap;
  src: url('/static/fonts/plex-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'IBM Plex Sans'; font-style: normal; font-weight: 100 700;
  font-stretch: 100%; font-display: swap;
  src: url('/static/fonts/plex-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

:root {
  /* The site is light-only: the design system ships no dark theme. Declaring
     the scheme makes the browser render form controls, scrollbars and default
     backgrounds light even when the device is in dark mode — otherwise
     dark-mode UA styling leaks in and looks like a stray half-theme. */
  color-scheme: light;

  /* ── Navy — the primary. Marinblå, per the brief. ── */
  --navy-100: #E7EFF6;
  --navy-200: #CBDDEB;
  --navy-300: #7FA3C4;
  --navy-400: #4C7FB0;
  --navy-500: #2A639A;
  --navy-600: #1F5080;
  --navy-700: #17395A;  /* primary */
  --navy-800: #10263C;
  --navy-900: #0A1826;

  /* ── Graphite — the neutrals. Cool, but flatter than the navy. ── */
  --ink-900: #12161A;
  --ink-700: #333B44;
  --ink-500: #5E6874;
  --ink-300: #9AA5B1;
  --line-1:  #DCE3EA;
  --line-2:  #EDF1F5;
  --paper-0: #FFFFFF;
  --paper-1: #F5F8FA;  /* section tint */
  --paper-2: #E9EFF5;

  /* ── Semantic ── */
  --success: #1F7A4D;
  --warning: #B45309;
  --danger:  #B3261E;

  /* ── Signal — the ONE accent.
        Checkmarks, chips, kickers and defect markers ONLY, never a large
        surface: it reads as a warning the moment it covers area, and on an
        inspector's site that is actively misleading. ── */
  --signal-100: #FBF1E2;
  --signal-300: #E0A15A;
  --signal-500: #B45309;
  --signal-600: #92400E;

  /* Kept because admin.css references the amber family by name. Same hue,
     same role — small highlights only. */
  --amber-100: var(--signal-100);
  --amber-300: var(--signal-300);
  --amber-500: var(--signal-500);
  --amber-600: var(--signal-600);

  /* The blue family under the names admin.css uses. Every one resolves to the
     navy that plays the same part, which is what lets the ported backoffice
     re-skin without an edit. */
  --blue-100: var(--navy-100);
  --blue-200: var(--navy-200);
  --blue-300: var(--navy-300);
  --blue-400: var(--navy-400);
  --blue-500: var(--navy-500);
  --blue-600: var(--navy-600);
  --blue-700: var(--navy-700);
  --blue-800: var(--navy-800);

  /* ── Role aliases ── */
  --brand-gradient: linear-gradient(135deg, var(--navy-700), var(--navy-900));
  --text-heading: var(--navy-900);
  --text-body: var(--ink-700);
  --text-muted: var(--ink-500);
  --text-on-brand: #FFFFFF;
  --surface-page: var(--paper-0);
  --surface-section: var(--paper-1);
  --surface-card: var(--paper-0);
  --border-card: var(--line-1);
  --accent: var(--navy-600);
  --accent-strong: var(--navy-700);
  --link: var(--navy-600);
  --link-hover: var(--navy-700);
  --focus-ring: 0 0 0 3px var(--navy-200);

  /* ── Typography ──
     NOT the sibling project's uppercase condensed display. That is a roofing
     contractor's voice — loud, wide, shouted. This site argues that it is
     sober and technical, so the display face is the body face at 600 with
     tight leading and a hair of tracking. One family, four weights, no
     shouting. */
  --font-display: 'IBM Plex Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Arial, sans-serif;
  --font-body: var(--font-display);
  --font-mono: 'IBM Plex Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
  --display-xl: 600 clamp(34px, 5vw, 56px)/1.08 var(--font-display);
  --display-lg: 600 clamp(28px, 3.4vw, 40px)/1.12 var(--font-display);
  --display-md: 600 clamp(22px, 2.2vw, 28px)/1.2 var(--font-display);
  --display-sm: 600 19px/1.25 var(--font-display);
  --display-tracking: -0.01em;
  --kicker: 600 12px/1.2 var(--font-display);
  --kicker-tracking: 0.12em;
  --body-lg: 400 18px/1.65 var(--font-body);
  --body-md: 400 16px/1.65 var(--font-body);
  --body-sm: 400 14px/1.55 var(--font-body);
  --label: 600 14px/1.2 var(--font-body);

  /* ── Spacing ── */
  --sp-1: 4px;  --sp-2: 8px;  --sp-3: 12px; --sp-4: 16px;
  --sp-5: 24px; --sp-6: 32px; --sp-7: 48px; --sp-8: 64px; --sp-9: 96px;
  --container: 1140px;
  --section-pad: 96px;

  /* ── Effects ──
     Buttons are --radius-sm (6px), never pills. */
  --radius-sm: 6px;
  --radius-md: 10px;
  --radius-lg: 16px;
  --radius-pill: 999px;
  --shadow-card: 0 1px 2px rgba(10,24,38,.06), 0 8px 24px rgba(10,24,38,.06);
  --shadow-raised: 0 12px 40px rgba(10,24,38,.14);
  --ease: cubic-bezier(.2,.7,.3,1);
  --speed: 160ms;

  /* ══ Legacy aliases — remapped by ROLE, not by hue ═══════════════════════
     admin.css was written against the sibling project's palette (sand/coral/
     ocean, a warm scheme). Every name below resolves to the token
     that plays the SAME PART in the interface, so the backoffice re-skins
     without a single edit to that file. The names are legacy: do not
     reference them in new CSS. */
  --sand-100:    var(--paper-1);   /* page background            */
  --sand-200:    var(--paper-0);   /* cards / raised panels      */
  --sand-300:    var(--line-1);    /* hairline borders / inputs  */
  --sand-400:    var(--ink-300);   /* stronger borders           */
  --coral:       var(--blue-600);  /* primary action             */
  --coral-dark:  var(--blue-700);  /* primary hover / pressed    */
  --coral-muted: var(--blue-100);  /* subtle primary fills       */
  --ocean-deep:  var(--ink-900);   /* headings / body text       */
  --ocean-mid:   var(--ink-700);   /* field labels               */
  --ocean-light: var(--ink-500);   /* muted text                 */
  --tide:        var(--blue-500);  /* selection / highlight      */
  --tide-light:  var(--blue-200);
  --white:       var(--paper-0);   /* cards / text on dark       */
  --error:       var(--danger);
  --charcoal:      var(--ink-900); /* headings / body text       */
  --charcoal-soft: var(--ink-700); /* field labels               */
  --warm-white:    var(--paper-1); /* page background            */
  --panel-2:       var(--paper-2); /* deeper panel tint          */
  --border:        var(--line-1);  /* hairline                   */
  /* The "roof" family is the sibling project's red; here it is purely the
     danger role — cms-counter.js paints an over-limit character counter with
     it, so it must read as a warning and never as a success. */
  --roof:      var(--danger);
  --roof-dark: #A9332C;
  --roof-soft: #FBE9E8;

  /* admin.css animates with --ease-out; the design system's curve is --ease.
     Same role, different name. */
  --ease-out: var(--ease);

  /* The 4pt scale under admin.css's name. */
  --space-1: var(--sp-1); --space-2: var(--sp-2); --space-3: var(--sp-3);
  --space-4: var(--sp-4); --space-5: var(--sp-5); --space-6: var(--sp-6);
  --space-7: var(--sp-7); --space-8: var(--sp-8); --space-9: var(--sp-9);

  /* admin.css uses a serif for the sibling project's wordmark. Here the
     wordmark is set in the display face, so the serif role collapses onto it. */
  --font-serif: var(--font-display);
}

*, *::before, *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

/* The reset above also zeroes the ONE margin that must survive it: the user
   agent centres a showModal() dialog with `margin: auto` on `dialog`, so the
   blanket margin: 0 pinned every modal (the CMS upload dialog among them) to
   the viewport's top-left corner. Restore it here, beside the rule that broke
   it, so the next reset audit sees the pair together. */
dialog {
  margin: auto;
}

html {
  scroll-behavior: smooth;
  font-size: 16px;
}

body {
  font-family: var(--font-body);
  background-color: var(--surface-page);
  color: var(--text-body);
  -webkit-font-smoothing: antialiased;
  line-height: 1.6;
  /* Taps are always clicks on interactive elements: kills iOS double-tap-zoom
     disambiguation, which otherwise eats the first tap on buttons. touch-action
     does NOT inherit, so this must name the elements themselves, not body.
     Pinch-zoom stays. */
  button, a, input, select, textarea {
    touch-action: manipulation;
  }
}

/* Last lines are never left as a single orphaned word. Every measure on this
   site is capped — headings at 16-22ch, leads at 62ch, card text inside a
   250px column — which is exactly the width at which a greedy line-breaker
   strands one word on a line of its own, several times per screen. */
p {
  text-wrap: pretty;
}

img {
  display: block;
  max-width: 100%;
  height: auto;
}

a {
  color: inherit;
  text-decoration: none;
}

button {
  cursor: pointer;
  font-family: var(--font-body);
  border: none;
  background: none;
}

input, textarea, select {
  font-family: var(--font-body);
}

/* Visible, brand-coloured focus for keyboard users on every interactive
   element, including ones the admin stylesheet styles itself. :focus-visible
   keeps it off mouse clicks. */
:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
  border-radius: var(--radius-sm);
}

/* ── Brand lockup ──
   The wordmark is set in TYPE, not artwork. There is no supplied logo file, and
   inventing one would be a design decision the client has not made — so the
   backoffice surfaces render the same mark-plus-word the public nav does. */
.admin-brand,
.login-brand {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-3);
  font: 400 20px/1 var(--font-display);
  text-decoration: none;
}
.admin-brand strong,
.login-brand strong { font-weight: 600; }
/* .admin-brand's colour is NOT set here: admin.css loads after this file and
   would win. See the BesiktaBygget section at the end of admin.css. */
.login-brand { color: var(--navy-900); }

.brand-plate-img {
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  border-radius: var(--radius-sm);
  background: var(--navy-700);
  color: #fff;
}

/* ── The primary button ───────────────────────────────────────────
   ONE definition, for the public site and the backoffice both. There used to
   be two — a gradient one here and a flat navy one in layout.css — and which
   of them a button got was decided by which stylesheets that page happened to
   load. Two designs for one class name is a coin toss dressed as a cascade.

   Radius is --radius-sm (6px), never a pill. Hover darkens one step, press
   sinks 1px: the behaviour this file's comment always described, now the
   behaviour it actually has. */
.btn-primary {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  font: var(--label);
  letter-spacing: .01em;
  padding: 13px var(--sp-5);
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  background: var(--navy-700);
  color: var(--text-on-brand);
  cursor: pointer;
  text-decoration: none;
  white-space: nowrap;
  transition: background var(--speed) var(--ease), border-color var(--speed) var(--ease),
              color var(--speed) var(--ease), transform var(--speed) var(--ease);
}

.btn-primary:hover {
  background: var(--navy-600);
  color: var(--text-on-brand);
}

.btn-primary:active {
  transform: translateY(1px);
}

/* .container, .section-title, .section-label, .field-label, .field-input and
   .required used to follow. The first duplicated layout.css exactly; the rest
   were the sibling project's, ported wholesale and then left behind — the two
   section utilities are uppercase 700-weight display type this brand explicitly
   rejected, and nothing on either surface referenced any of them. .field-label
   was the exception that mattered: it was ALSO defined in pages.css with
   different values, so the public form's labels came out one way on the pages
   that loaded that sheet and another way on the pages that did not. The form's
   field primitives now live with the form, in form.css. */
