/* Organic — design-system tokens and component classes.
 *
 * Ported from the Claude Design project "Portal.nilsaro.com redesign"
 * (_ds/organic-724e5cfb-9657-42fa-8e30-255a830a273f/styles.css). Keep edits in
 * step with that source: it is the system's own reference, and this file is a
 * copy, not a fork.
 *
 * This is the platform's system, not one product's skin. It replaces Modernist
 * in place — same filename role, same five shells (templates/base.html, the
 * product and scan shells, the platform console and its auth screens) — so
 * every Nilsaro surface moves together. static/css/main.css is what the portal
 * used before Modernist and is kept only for the screens still naming its
 * classes; nothing new should link it.
 *
 * Only the portal has an Organic design. The product and console screens
 * inherit these tokens — ground, type, radii, elevation — with their markup
 * untouched, because no Organic design exists for them. Expect them to read as
 * rethemed, not redesigned.
 *
 * The product shell (templates/depotkontroll/base_product.html) still does not
 * extend base.html, but the reason is scope rather than styling: a product
 * carries its own chrome and navigation, not the portal's.
 *
 * The @import of Caprasimo and Figtree present in the source is dropped here.
 * The shell links the fonts in <head> with preconnect, which starts the
 * download earlier than an @import nested inside a stylesheet can.
 */

:root {
  --color-bg: #f5ead8;
  --color-surface: #ebddc5;
  --color-text: #201e1d;
  --color-accent: #c67139;
  --color-accent-2: #7a8a5e;
  --color-divider: color-mix(in srgb, #201e1d 16%, transparent);

  /* The logo's own three colours, exactly as drawn. They are a set: the blue
     and the cyan are letterforms sitting on the navy, and they only hold up on
     that ground. Organic's accent is terracotta and shares none of this hue, so
     unlike under Modernist there is no longer a "one hue, two seats" relation
     to keep — these are simply the mark's colours. The redesign still paints
     the mark on --color-brand-navy wherever it appears. */
  --color-brand-navy: #162c55;
  --color-brand-blue: #2eb6fe;
  --color-brand-cyan: #0af9e9;

  /* Tonal ramps — generated in OKLCH on one shared lightness scale, so the
     same step of any role matches the others in visual value. */
  --color-neutral-100: #f9f4ed;
  --color-neutral-200: #eee7db;
  --color-neutral-300: #dcd3c4;
  --color-neutral-400: #c0b6a5;
  --color-neutral-500: #a19786;
  --color-neutral-600: #82796a;
  --color-neutral-700: #645c50;
  --color-neutral-800: #474238;
  --color-neutral-900: #2e2b25;

  --color-accent-100: #fff2eb;
  --color-accent-200: #ffe1d0;
  --color-accent-300: #ffc6a5;
  --color-accent-400: #f6a06b;
  --color-accent-500: #d67f48;
  --color-accent-600: #b2622d;
  --color-accent-700: #8c491a;
  --color-accent-800: #643312;
  --color-accent-900: #402310;

  /* Alarm, kept separate from brand, and carried across from Modernist
     unchanged. The argument for keeping it is stronger under Organic than it
     was under Modernist: a terracotta accent sits close enough to red in hue
     that letting "out of service" borrow it would leave a warning and a label
     nearly the same colour. The accent says what a control does; these two
     ramps are the only thing screens should use to mean trouble. Danger is the
     pre-rebrand accent ramp, unchanged. */
  --color-danger: #dd2b0f;
  --color-danger-100: #fff2ef;
  --color-danger-200: #ffe0d9;
  --color-danger-300: #ffc4b8;
  --color-danger-600: #dd2b0f;
  --color-danger-700: #ae1800;
  --color-danger-800: #7c1405;

  --color-warning: #b56200;
  --color-warning-100: #fbf4ef;
  --color-warning-200: #f5e4d8;
  --color-warning-300: #eecdb5;
  --color-warning-600: #b56200;
  --color-warning-700: #8c4a00;
  --color-warning-800: #653300;

  --color-accent-2-100: #f0fae1;
  --color-accent-2-200: #e1eecc;
  --color-accent-2-300: #ccdbb2;
  --color-accent-2-400: #aebf92;
  --color-accent-2-500: #8fa073;
  --color-accent-2-600: #728157;
  --color-accent-2-700: #56633f;
  --color-accent-2-800: #3d472b;
  --color-accent-2-900: #272e1b;

  --font-heading: "Caprasimo", system-ui, sans-serif;
  --font-heading-weight: 400;
  --font-body: "Figtree", system-ui, sans-serif;
  /* Organic names no mono face. Kept from Modernist: the console, the audit log
     and the token and backup-code screens all set data in it. */
  --font-mono: ui-monospace, SFMono-Regular, Menlo, monospace;

  /* Density 1.10x, baked into the scale by the system. */
  --space-1: 4.4px;
  --space-2: 8.8px;
  --space-3: 13.2px;
  --space-4: 17.6px;
  --space-6: 26.4px;
  --space-8: 35.2px;

  /* Modernist drew these at 0px. Organic over-rounds: containers take
     --radius-lg, and buttons and inputs go to 999px in the component layer. */
  --radius-sm: 8px;
  --radius-md: 16px;
  --radius-lg: 28px;

  --shadow-sm: 0 1px 2px color-mix(in srgb, #2e2b25 14%, transparent);
  --shadow-md: 0 3px 10px color-mix(in srgb, #2e2b25 16%, transparent);
  --shadow-lg: 0 12px 32px color-mix(in srgb, #2e2b25 22%, transparent);
}

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

body {
  margin: 0;
  background: var(--color-bg);
  color: var(--color-text);
  font-family: var(--font-body);
  font-size: 15px;
  line-height: 1.55;
  font-weight: 400;
}

h1, h2, h3, h4, h5, h6 {
  font-family: var(--font-heading); font-weight: var(--font-heading-weight);
  line-height: 1.12; letter-spacing: -0.015em; margin: 0 0 var(--space-2);
}
h1 { font-size: 42px; }
h2 { font-size: 32px; }
h3 { font-size: 25px; }
h4 { font-size: 20px; }
h5 { font-size: 16px; }
h6 { font-size: 13px; letter-spacing: 0.08em; text-transform: uppercase; }

p { margin: 0 0 var(--space-3); }
/* Links take the 700 step rather than --color-accent itself. Running text is
   the one place the accent has to survive at 15px and regular weight, and 700
   reaches 5.7:1 on --color-bg where the base accent sits at 3.0:1. Buttons,
   kickers and borders keep the base accent — they are bold, large, or not text
   at all. Organic's own guide says the same thing: the accent-to-ground pair is
   tuned for chrome and large text, so paragraph-size accent text takes a deep
   ramp step. The redesign file overrides <a> to the 700 step for this reason
   too; this rule means the templates do not have to. */
a { color: var(--color-accent-700); text-underline-offset: 3px; }
a:hover { color: var(--color-accent-800); }

/* — brand mark — */
/* The logo is drawn for the navy, so on a light ground it brings the navy with
   it as a tile: the PNG is transparent outside the letterform, and the
   background here shows through it. On a dark ground use .nilsaro-mark--bare,
   which drops the tile and lets the mark sit straight on the surface. */
.nilsaro-mark {
  width: 26px; height: 26px; flex: none;
  background: var(--color-brand-navy);
  padding: 5px 7px; object-fit: contain;
}
.nilsaro-mark--bare { background: none; padding: 0; width: 15px; height: 20px; }
img { display: block; max-width: 100%; }
figure { margin: 0; }
figcaption {
  font-size: 11px; margin-top: var(--space-1);
  color: color-mix(in srgb, var(--color-text) 55%, transparent);
}
.text-muted { color: color-mix(in srgb, var(--color-text) 55%, transparent); }

:focus { outline: none; }
:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 2px; }
::selection { background: color-mix(in srgb, var(--color-accent) 30%, transparent); }

/* — rules — */
/* Organic prefers whitespace to rules and draws this at 1px where Modernist
   drew 2px. Its guide says to avoid the class altogether. */
.hr { height: 1px; border: 0; margin: var(--space-4) 0; background: var(--color-divider); }

/* — buttons — */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  cursor: pointer; text-decoration: none;
  font-family: var(--font-heading); font-weight: var(--font-heading-weight);
  font-size: 14px; line-height: 1.2; color: var(--color-text);
  background: transparent; border: 1px solid transparent;
  padding: var(--space-2) calc(var(--space-3) * 1.2);
  border-radius: var(--radius-md);
}
.btn svg { display: block; }
.btn:disabled, .btn[aria-disabled="true"] { opacity: 0.45; cursor: not-allowed; }
.btn-primary { background: var(--color-accent); color: var(--color-bg); }
.btn-primary:hover { background: var(--color-accent-600); color: var(--color-bg); }
.btn-primary:active { background: var(--color-accent-700); }
.btn-secondary { border-color: var(--color-divider); }
.btn-secondary:hover { background: color-mix(in srgb, var(--color-text) 7%, transparent); color: var(--color-text); }
.btn-secondary:active { background: color-mix(in srgb, var(--color-text) 14%, transparent); }
.btn-ghost { color: var(--color-accent); padding-inline: var(--space-1); }
.btn-ghost:hover { background: color-mix(in srgb, var(--color-accent) 10%, transparent); }
.btn-ghost:active { background: color-mix(in srgb, var(--color-accent) 18%, transparent); }
.btn-danger { color: var(--color-danger-700); border: 1px solid var(--color-danger); }
.btn-danger:hover { background: var(--color-danger-100); color: var(--color-danger-800); }
.btn-icon { width: 36px; height: 36px; padding: 0; }
.btn-block { width: 100%; margin-top: var(--space-2); justify-content: flex-start; text-align: left; }

/* — forms — */
.field > label, label.field-label {
  display: block; font-size: 12px; margin-bottom: 5px;
  color: color-mix(in srgb, var(--color-text) 70%, transparent);
}
.input, input[type="text"], input[type="search"], input[type="number"],
input[type="email"], input[type="password"], input[type="date"], select, textarea {
  width: 100%; min-height: 36px; padding: 6px 10px; font: inherit;
  font-size: 14px; color: var(--color-text); caret-color: var(--color-accent);
  background: var(--color-surface);
  border: 1px solid var(--color-divider); border-radius: var(--radius-md);
}
.input:hover, input:hover, select:hover, textarea:hover {
  border-color: color-mix(in srgb, var(--color-text) 45%, transparent);
}
.input:focus-visible, input:focus-visible, select:focus-visible, textarea:focus-visible {
  border-color: var(--color-accent); outline-offset: 0;
}
textarea, textarea.input { min-height: 90px; resize: vertical; }
select.input, select { appearance: none; background-image: none; }
input[type="checkbox"], input[type="radio"] { width: auto; min-height: 0; }

.radio { display: inline-flex; align-items: center; gap: 8px; cursor: pointer; font-size: 14px; }
.radio input { position: absolute; opacity: 0; width: 0; height: 0; pointer-events: none; }
.radio .dot { width: 16px; height: 16px; flex: none; border-radius: 50%; border: 1.5px solid var(--color-divider); }
.radio:hover .dot { border-color: var(--color-accent); }
.radio input:checked + .dot {
  border-color: var(--color-accent); background: var(--color-accent);
  box-shadow: inset 0 0 0 4px var(--color-bg);
}
.radio input:focus-visible + .dot { outline: 2px solid var(--color-accent); outline-offset: 2px; }

/* The segmented control from the system source, restored here when the portal
   redesign needed it for the notifications filter. Native radios underneath, so
   it is one field, keyboard-operable, and submits without script. */
.seg {
  display: inline-flex; overflow: hidden;
  border: 1px solid var(--color-divider); border-radius: var(--radius-md);
}
.seg-opt {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 7px 12px; font-size: 13px; cursor: pointer;
  color: var(--color-text); text-decoration: none;
}
.seg-opt input { position: absolute; opacity: 0; width: 0; height: 0; pointer-events: none; }
.seg-opt + .seg-opt { border-left: 1px solid var(--color-divider); }
.seg-opt:has(input:checked),
.seg-opt[aria-current="page"] { background: var(--color-accent); color: var(--color-bg); }
.seg-opt:not(:has(input:checked)):not([aria-current="page"]):hover {
  background: color-mix(in srgb, var(--color-text) 7%, transparent);
}
.seg-opt:has(input:focus-visible) { outline: 2px solid var(--color-accent); outline-offset: -2px; }

/* — cards — */
.card {
  display: flex; flex-direction: column; gap: var(--space-2);
  padding: var(--space-3); border-radius: var(--radius-md); background: var(--color-surface);
}
.card-kicker { font-size: 10px; letter-spacing: 0.1em; text-transform: uppercase; color: var(--color-accent); }
.card-title { font-family: var(--font-heading); font-weight: var(--font-heading-weight); font-size: 17px; line-height: 1.2; }
.card-body { margin: 0; font-size: 13px; opacity: 0.8; flex: 1; }
.card-meta { display: flex; align-items: center; gap: 6px; font-size: 11px; color: color-mix(in srgb, var(--color-text) 50%, transparent); }
.elev-sm { box-shadow: var(--shadow-sm); }
.elev-md { box-shadow: var(--shadow-md); }
.elev-lg { box-shadow: var(--shadow-lg); }

/* — tags — */
/* Every tag carries a hairline, and that is the part doing the work.
 *
 * The fill alone cannot give a tag an edge, because tags appear on three
 * different grounds — a white panel, the #f3f2f2 sidebar, and the #e9e7e6 page
 * — and those three span exactly the range the light ramp steps occupy. Any
 * single tint is invisible against one of them: the 100 step sat within ΔL 1 of
 * the sidebar, and moving to 200 merely swapped which ground it disappeared on,
 * landing within ΔL 0.2 of the page. Measured, not guessed.
 *
 * A border decouples the edge from the ground. At the 300 step the weakest edge
 * against any of the three is ΔL 5.9 — a definite hairline everywhere — while
 * sitting only ΔL 6 from its own fill, so it still reads as a quiet pill rather
 * than a boxed one. The 400 step would be firmer and would look like a button.
 *
 * Padding drops a pixel to pay for the border, so the outer size is unchanged
 * and no row grows when a tag appears in it.
 */
.tag {
  display: inline-flex; align-items: center; font-size: 11px;
  letter-spacing: 0.02em; padding: 2px 9px;
  border: 1px solid transparent;
  border-radius: calc(var(--radius-md) * 0.75);
}
.tag-accent {
  background: var(--color-accent-200); border-color: var(--color-accent-300);
  color: var(--color-accent-800);
}
.tag-accent-2 {
  background: var(--color-accent-2-200); border-color: var(--color-accent-2-300);
  color: var(--color-accent-2-800);
}
.tag-neutral {
  background: var(--color-neutral-200); border-color: var(--color-neutral-300);
  color: var(--color-neutral-800);
}
.tag-outline { border-color: var(--color-accent); color: var(--color-accent); }
/* Use these two, not tag-accent, when the tag reports a problem. The accent
   tags say "this is a kind of thing"; these say "something is wrong". */
.tag-danger {
  background: var(--color-danger-200); border-color: var(--color-danger-300);
  color: var(--color-danger-800);
}
.tag-warning {
  background: var(--color-warning-200); border-color: var(--color-warning-300);
  color: var(--color-warning-800);
}

/* — tables — */
.table { width: 100%; border-collapse: collapse; font-size: 14px; }
.table th {
  text-align: left; font-size: 11px; letter-spacing: 0.08em; text-transform: uppercase;
  color: color-mix(in srgb, var(--color-text) 60%, transparent);
  padding: var(--space-2); border-bottom: 1px solid var(--color-divider);
}
.table td { padding: var(--space-2); border-bottom: 1px solid var(--color-divider); }
.table tbody tr:hover { background: color-mix(in srgb, var(--color-text) 4%, transparent); }

/* — dialog — */
.dialog-backdrop {
  position: fixed; inset: 0; display: grid; place-items: center;
  padding: var(--space-4);
  background: color-mix(in srgb, var(--color-neutral-900) 50%, transparent);
}
.dialog {
  width: min(440px, 100%); display: flex; flex-direction: column; gap: var(--space-3);
  padding: var(--space-4); border-radius: var(--radius-lg);
  background: var(--color-surface); box-shadow: var(--shadow-lg);
}
.dialog-title { font-family: var(--font-heading); font-weight: var(--font-heading-weight); font-size: 20px; }
.dialog-body { font-size: 14px; opacity: 0.85; }
.dialog-actions { display: flex; justify-content: flex-end; gap: var(--space-2); margin-top: var(--space-2); }

/* A sign-out control is a POST (a GET that ends a session can be triggered by
   any other site with an <img> tag), so it is a form whose button looks like the
   links beside it. */
.inline-form { display: inline; margin: 0; }
.link-button { background: none; border: 0; padding: 0; margin: 0; font: inherit; color: inherit; cursor: pointer; text-decoration: none; }
.link-button:hover { text-decoration: underline; }

/* — rounded frame: everything softens, small controls go pill —
 *
 * This block is the whole of Organic's "over-round" direction and the single
 * largest visual break from Modernist, which drew every --radius-* at 0px.
 * It is last in the file on purpose: it restates radii the component rules
 * above already set, and has to win.
 *
 * The bare element selectors mirror the .input rule above — Django renders
 * plain <input>/<select> for most fields, and a form of pill inputs with one
 * square one is worse than either choice made consistently.
 *
 * textarea is deliberately not in the pill list. A multi-line box at 999px
 * pinches its own first and last lines; the design sets those to 20px inline
 * wherever it uses one, which is --radius-lg here.
 */
.card, .dialog { border-radius: calc(var(--radius-lg) * 1.15); }
.btn, .tag, .seg,
.input, input[type="text"], input[type="search"], input[type="number"],
input[type="email"], input[type="password"], input[type="date"], select {
  border-radius: 999px;
}
.input, input[type="text"], input[type="search"], input[type="number"],
input[type="email"], input[type="password"], input[type="date"], select {
  padding-inline: 14px;
}
textarea, textarea.input { border-radius: var(--radius-lg); }
