/* The Ubuntu font, served from our own static/ rather than Google Fonts -
   loading it from Google sends every visitor's IP address to Google (a
   GDPR/RODO problem). Files from the @fontsource/ubuntu npm package,
   licence in ../fonts/LICENSE.txt.

   Each weight is split in two files by unicode-range: "latin" (English
   letters) and "latin-ext" (ą, ę, ł, č, ș, ...). The browser downloads
   a file only when a page actually uses a character from its range. */
@font-face {
    font-family: "Ubuntu";
    font-style: normal;
    font-weight: 400;
    font-display: swap;
    src: url("../fonts/ubuntu-latin-400-normal.4a8b9af22b31.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: "Ubuntu";
    font-style: normal;
    font-weight: 400;
    font-display: swap;
    src: url("../fonts/ubuntu-latin-ext-400-normal.530aea4a339a.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;
}

@font-face {
    font-family: "Ubuntu";
    font-style: normal;
    font-weight: 700;
    font-display: swap;
    src: url("../fonts/ubuntu-latin-700-normal.9418887ae687.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: "Ubuntu";
    font-style: normal;
    font-weight: 700;
    font-display: swap;
    src: url("../fonts/ubuntu-latin-ext-700-normal.49dea29c68f0.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 {
    /* Tells the browser the site is dark, so the controls it draws itself -
       number arrows, a <select>'s open list, scrollbars, the date picker -
       are drawn dark too, instead of light on a dark page. */
    color-scheme: dark;
    --gray-0: #000000;              /* background */
    --gray-1: #0b0b0b;              /* use next color */
    --gray-2: #1c1c1c;              /* for when the item */
    --gray-3: #292929;              /* is inside a block */
    --gray-4: #363636;              /* of that color */
    --border: var(--gray-3);
    --border-lighter: var(--gray-4);
    --text: #f6f6f6;                /* normal text */
    --text-darker: #c2c2c2;         /* not selected */
    --text-muted: #909090;          /* muted or not selected inside a list */
    --red: #e30000;
    --red-used: #ff0000;
    --danger: #880000;
    --danger-used: #990000;
    --red-pastel: #ffbbbb;          /* selected / error */
    --green-pastel: #bbffcc;        /* success / ok */
    --yellow-pastel: #ffffbb;       /* warning */
    --radius: 0.4rem;                 /* buttons */
    --radius-big: 1rem;               /* main boxes */
    --font-sm: 0.9rem;                /* labels */
    --font-xs: 0.75rem;               /* other small */
    --vpad: 0.5rem;                   /* buttons */
    --hpad: 1rem;                     /* buttons */
    --trans: 0.15s;
    --card-dist: 0.65rem;
    --width-narrow: 20rem;            /* short forms - login, forgot password */
    --width-form: 30rem;              /* forms, the profile */
    --width-page: 60rem;              /* details pages */

    /* color: color-mix(in srgb, blue 80%, black);  for future reference */
}

* {
    box-sizing: border-box;
}

h1 {
    margin: 0.5rem;
}

html, body {
    height: 100%;
    margin: 0;
}

/* A column: the page's main content, then (where there is one) the footer
   underneath - not beside it. */
body {
    display: flex;
    flex-direction: column;
    min-height: 100dvh;
    /* Clear of what a phone draws over the screen - the notch, the status
       bar, the rounded corners, the home bar - once the page has the whole
       screen (viewport-fit=cover in base.html). env() gives each one's size;
       0 on a computer and on phones without them, so nothing moves there.
       Fixed elements ignore this - they keep clear themselves (sidebar.css,
       welcome.css). */
    padding: env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left);
    background: var(--gray-0);
    color: var(--text);
    font-family: "Ubuntu", system-ui, -apple-system, "Segoe UI", sans-serif;
}

/* Full-page watermark, pinned behind everything else. `contain` shows the
   whole image without cropping it: fits to height when there's room, then
   flips to fitting by width once the viewport gets too narrow/tall.
   `background-position: left center` keeps it pinned to the left edge
   always, only ever centering vertically. The file itself has a solid
   black canvas rather than a transparent one, so `mix-blend-mode: screen`
   is what makes the black part disappear into the page background instead
   of drawing a hard black rectangle - only the lighter monogram shows
   through. */
body::before {
    content: "";
    position: fixed;
    inset: 0;
    z-index: -1;
    filter: brightness(75%);
    pointer-events: none;
    background-image: url("../img/background-logo.5910498d577c.webp");
    background-repeat: no-repeat;
    background-position: left center;
    background-size: contain;
    mix-blend-mode: screen;
}

.btn {
    padding: var(--vpad) var(--hpad);
    color: var(--text);
    text-decoration: none;
    border: 0;
    border-radius: var(--radius);
    transition: background-color var(--trans) ease;
    font: inherit;
}

.btn:hover {
    cursor: pointer
}

/* Button colours - .btn itself has none, so every button picks one:
   red for the main action (Save, Login), gray for the lesser one beside it
   (Cancel) or a quiet one on its own (Edit on the profile page). */
.btn.btn--red {
    background: var(--red);
}

.btn.btn--red:hover {
    background: var(--red-used);
}

.btn.btn--gray {
    background: var(--gray-2);
}

.btn.btn--gray:hover {
    background: var(--gray-3);
}

.btn.btn--danger {
    background: var(--danger);
}

.btn.btn--danger:hover {
    background: var(--danger-used);
}

/* A button shown but not usable now (aria-disabled - e.g. Previous on a
   list's first page): faded, whatever its colour (opacity), and the mouse
   goes through it (pointer-events: none) - so no hover colour and no
   pointer cursor suggesting it can be clicked. */
.btn[aria-disabled="true"] {
    opacity: 0.5;
    pointer-events: none;
}

/* A row of buttons, right-aligned - used for every button that ends a form
   or card, even a lone one, so they all line up the same way. It sets no
   outer spacing: how far it sits from what's above is the container's call
   (see .form .actions). flex-wrap: more buttons than fit (a device's
   History, Deactivate, Company, Edit, Calibrate on a phone) go on to a
   second line, still right-aligned, instead of running off the card. */
.actions {
    display: flex;
    flex-wrap: wrap;
    justify-content: flex-end;
    gap: 0.5rem;
}

/* A row of buttons in the middle of things rather than at the end of a
   form or card (that's .actions): left-aligned, wrapping onto more lines on
   a narrow screen - a company's owner invitation (Send again, Cancel), the
   companies to give away before deleting your account. No outer spacing,
   like .actions. */
.button-row {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
}

/* A form of buttons inside the row (a ticket's Accept / Close, a booking's
   Cancel / Mark done, beside Back): display: contents - the form itself
   makes no box, so its buttons become the row's own items and get the row's
   gap, like Back. */
.actions > form {
    display: contents;
}

/* A page without the sidebar (login, create account) with its content in the
   middle of the screen. flex: 1 makes <main> take all the height <body> - a
   flex column - has left after the footer, so there's room to centre in,
   both ways. */
.page-center {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
}

.card {
    padding: 1.5rem;
    background: var(--gray-1);
    border: 1px solid var(--border);
    border-radius: var(--radius-big);
}

/* A row at the top of a card: its heading on the left, a search on the
   right (the dashboard's Milling machines, every list page) -
   space-between pushes them to opposite edges, align-items centres them on
   one line, and on a narrow screen the search wraps under the heading. The
   heading's own margins are reset - the row's gap and margin space it. */
.card__header {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    align-items: center;
    gap: 0.5rem 1rem;
    margin-bottom: 1rem;
}

.card__header h1,
.card__header h2 {
    margin: 0;
}

/* The site footer (common/footer.html). margin-top: auto pushes it to the
   bottom of whatever flex column it's in - <body> on login/create account,
   .app-main on pages with the sidebar - however short the page above it. */
.site-footer {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 0.25rem 1rem;
    margin-top: auto;
    padding: 1rem;
    font-size: var(--font-xs);
    color: var(--text-muted);
}

.site-footer a {
    color: var(--text-darker);
}

.site-footer a:hover {
    color: var(--text);
}

/* Form feedback. Only the look lives here - where a message sits on the
   page (e.g. centered above the login box) is up to that page's own CSS.
   Pastel rather than full red: --red on the near-black background is too
   dark to read comfortably as text. */
.error,
.message {
    margin: 0 0 0.5rem;
    font-size: var(--font-sm);
}

.error {
    color: var(--red-pastel);
}

/* Above a centred card (login, create account, password pages), a message
   is as wide as the form below it (.form's max-width) and centred - a long
   one would otherwise stretch wider than the card. */
.page-center > .error,
.page-center > .message {
    width: 100%;
    max-width: var(--width-form);
    text-align: center;
}

/* A centred page with a short form (login, forgot password): the card and
   the messages above it at --width-narrow instead of --width-form. Has to
   come after the rule above - the message selectors are equally specific,
   so the later one wins. */
.page-center--narrow .form,
.page-center--narrow > .error,
.page-center--narrow > .message {
    max-width: var(--width-narrow);
}

.message {
    color: var(--green-pastel);
}

/* A notice that fades away by itself (common/messages.html,
   common/js/messages.js): its text and the × at the right end, on one
   line. The fade is opacity going to 0 once .message--leaving is added. */
.message--fading {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    transition: opacity 0.4s ease;
}

.message--leaving {
    opacity: 0;
}

/* The × - a bare button: no box, the notice's own colour, a bit bigger
   than the text so it's easier to hit. */
.message__close {
    padding: 0 0.25rem;
    border: 0;
    background: none;
    color: inherit;
    font-size: 1.25rem;
    line-height: 1;
    cursor: pointer;
}

@media (prefers-reduced-motion: reduce) {
    .message--fading {
        transition: none;
    }
}

/* === Page layout - the dashboard, the calibrate page, the details pages === */

/* A page as a column of cards, the full width of the content area (<main>
   centres its children - this one fills it). */
.page-stack {
    display: flex;
    flex-direction: column;
    gap: var(--card-dist);
    width: 100%;
}

/* A form page's <h1> (register, edit, invite, profile edit) - straight in
   <main> (>: a direct child), above its .form card. Placed like a
   .page-stack's heading: at the top, with the stack's gap (--card-dist)
   below - instead of the 0.5rem all round every <h1> gets above. */
.app-main > h1 {
    margin: 0 0 var(--card-dist);
}

/* The page's <h1> with something beside it on one line (a client's
   company, a machine's calibration state, a license's expiry) - under it on
   a narrow screen. baseline: the two texts' letters sit on the same line,
   though they're different sizes. */
.page-header {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0 1rem;
}

.page-header h1,
.page-header p {
    margin: 0;
}

/* A card's heading (and a pop-up's) - smaller than the browser's default,
   which is big enough to compete with the page's <h1>. */
.card-title {
    margin: 0 0 0.75rem;
    font-size: 1.1rem;
}

/* "Nothing to show" - quiet and centred, with an .empty-icon above it. */
.empty-state {
    margin: 0;
    color: var(--text-muted);
    text-align: center;
}

/* A <ul> without the browser's bullets and indent - the dashboard's tiles
   and licenses. */
.plain-list {
    margin: 0;
    padding: 0;
    list-style: none;
}

/* A tile that's a link as a whole - the dashboard's machines, the
   departments to report an issue to: a column of what's in it, a shade
   lighter than the card it sits in, as tall as its grid row. */
.tile__link {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    height: 100%;
    padding: 0.75rem;
    color: inherit;
    text-decoration: none;
    background: var(--gray-2);
    border: 1px solid var(--border-lighter);
    border-radius: var(--radius);
    transition: background-color var(--trans) ease;
}

/* Only where there's a real pointer - on a touch screen a tapped tile would
   stay highlighted after the finger has gone, looking selected. */
@media (hover: hover) {
    .tile__link:hover {
        background: var(--gray-3);
    }
}

/* Text for screen readers only - what a page shows another way, like
   "unread" after the sidebar's count. Not display: none or hidden, which
   screen readers skip too: a 1px box with everything outside it clipped. */
.visually-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
}

/* === Icons === */

/* The big icon above a "nothing to show" message (.empty-state). */
.empty-icon {
    font-size: 2.5rem;
}
