/*!
 * Modern dashboard skin — Bindu POS home screen.
 *
 * Presentation only, scoped to body.skin-purple so switching the business
 * theme colour turns it off. It styles through the markup that is already
 * there: no id, class or node is added or renamed, and the AJAX value hooks
 * (.total_sell, .total_purchase, …) are never touched.
 *
 * Each tile takes its accent from the semantic colour Tailwind already puts on
 * its icon chip, matched with :has(). Browsers without :has() simply keep the
 * plain card — nothing breaks.
 */

body.skin-purple {
    --dash-line:   #E7E7F0;
    --dash-ink:    #14181A;
    --dash-muted:  #6B7280;
    --dash-radius: 12px;
}

/* ------------------------------------------------------------------
   1. Welcome banner — compact, so the tiles get the room
   ------------------------------------------------------------------ */
/* The banner element also wraps the stat grid, so the gradient used to be
   painted across the top 132px only and the rest left to fall through to the
   page canvas -- a compact coloured header with the cards straddling onto
   light.

   The straddle is what produced the pale horizontal band under the first row
   of cards: the gradient ended in the middle of the grid, and the canvas
   showing below it read as a stray white shape rather than as the page. The
   gradient covers the whole banner now, so the only edge is the one beneath
   all of the cards.

   background-color is left alone: whatever the theme paints stays behind the
   gradient, and overriding it here is what put a light colour inside a dark
   header in the first place. */
body.skin-purple .theme-header-bg:not(.no-print) {
    background-repeat: no-repeat;
    background-size: 100% 100%;
    background-position: top left;
    /* The banner ends level with the bottom of the last card in it, so the
       card's own edge lands on the boundary and the next surface starts
       against it -- which is the strip that kept reappearing under the
       cards however the colours below were adjusted.

       Padding here rather than margin, deliberately: this is space INSIDE
       the banner, and the banner is the thing painting the colour. Padding
       extends what it paints, so the strip becomes part of the block above
       it instead of the start of whatever is below.

       The small-screen rule further down sets its own value; this is the
       wide-screen one. */
    padding-bottom: 50px;
}
/* Written for the welcome heading that used to sit in this banner. The
   greeting replaced it and is also an h1 in here, so this rule reached it and
   won on specificity -- the title stayed at 28px however small
   .dash-greeting__title asked to be. Excluded by name rather than deleted,
   because any other heading dropped into this banner should still get it. */
body.skin-purple .theme-header-bg:not(.no-print) h1:not(.dash-greeting__title) {
    font-size: clamp(1.3rem, 2.2vw, 1.75rem);
    letter-spacing: -.02em;
    margin-bottom: 0;
}

/* ------------------------------------------------------------------
   2. Stat tiles
   ------------------------------------------------------------------
   Scoped to .dash-stat-grid (the two 4-up rows on the dashboard).
   .tw-ring-1.tw-ring-gray-200 on its own is the standard widget wrapper
   used on every page, so an unscoped rule here put a 129px min-height on
   cards all over the app -- a collapsed Filters panel could not shrink. */
body.skin-purple .dash-stat-grid > .tw-ring-1.tw-ring-gray-200 {
    position: relative;
    border-radius: var(--dash-radius);
    /* Labels that wrap to two lines would otherwise make their tile taller
       than the rest of the row */
    min-height: 129px;
    box-shadow: 0 1px 2px rgba(20, 24, 26, .05), 0 10px 26px -18px rgba(20, 24, 26, .35);
    overflow: hidden;
    transition: transform .16s ease, box-shadow .16s ease;
}
body.skin-purple .dash-stat-grid > .tw-ring-1.tw-ring-gray-200:hover {
    transform: translateY(-2px);
    box-shadow: 0 1px 2px rgba(20, 24, 26, .05), 0 16px 34px -18px rgba(20, 24, 26, .45);
}

/* Accent rail along the top of every stat tile */
body.skin-purple .dash-stat-grid > .tw-ring-1.tw-ring-gray-200:has(> div > div > .tw-rounded-full)::before {
    content: "";
    position: absolute;
    inset-inline: 0;
    top: 0;
    height: 3px;
    background: var(--tile-accent, #94A3B8);
}

/* Semantic accents, read straight off the icon chip Tailwind already applied */
body.skin-purple .dash-stat-grid > .tw-ring-1.tw-ring-gray-200:has(.tw-bg-sky-100)    { --tile-accent: #0EA5E9; }
body.skin-purple .dash-stat-grid > .tw-ring-1.tw-ring-gray-200:has(.tw-bg-green-100)  { --tile-accent: #16A34A; }
body.skin-purple .dash-stat-grid > .tw-ring-1.tw-ring-gray-200:has(.tw-bg-yellow-100) { --tile-accent: #EAB308; }
body.skin-purple .dash-stat-grid > .tw-ring-1.tw-ring-gray-200:has(.tw-bg-red-100)    { --tile-accent: #EF4444; }

/* Icon chip: squircle instead of a circle, slightly stronger tint */
body.skin-purple .dash-stat-grid > .tw-ring-1.tw-ring-gray-200 .tw-rounded-full.tw-shrink-0 {
    border-radius: 11px;
}

/* Label: quiet micro-caps */
/* "Total Purchase Return" needs 161px in a 124px slot, so the stock
   .tw-truncate cut it to an ellipsis. Allowing two lines shows the full label;
   a min-height keeps every tile in the row the same height. */
body.skin-purple .dash-stat-grid > .tw-ring-1.tw-ring-gray-200 .tw-text-sm.tw-text-gray-500 {
    font-size: 10.5px;
    font-weight: 600;
    letter-spacing: .03em;
    text-transform: uppercase;
    color: var(--dash-muted);
    white-space: normal;
    overflow: visible;
    text-overflow: clip;
    line-height: 1.25;
    min-height: 2.5em;
    display: flex;
    align-items: center;
    gap: 4px;
    flex-wrap: wrap;
}

/* Value: the number is the point of the tile */
body.skin-purple .dash-stat-grid > .tw-ring-1.tw-ring-gray-200 .tw-flex-1 > p + p,
body.skin-purple .dash-stat-grid > .tw-ring-1.tw-ring-gray-200 .total_sell,
body.skin-purple .dash-stat-grid > .tw-ring-1.tw-ring-gray-200 .total_purchase,
body.skin-purple .dash-stat-grid > .tw-ring-1.tw-ring-gray-200 .invoice_due,
body.skin-purple .dash-stat-grid > .tw-ring-1.tw-ring-gray-200 .total_expense {
    font-size: clamp(1.05rem, 1.5vw, 1.4rem);
    font-weight: 700;
    letter-spacing: -.02em;
    color: var(--dash-ink);
    font-variant-numeric: tabular-nums;
    line-height: 1.2;
}

/* ------------------------------------------------------------------
   3. Chart / table panels
   ------------------------------------------------------------------ */
body.skin-purple .tw-bg-white.tw-rounded-xl.tw-shadow-sm {
    border-radius: var(--dash-radius);
}
body.skin-purple h3.tw-font-bold {
    font-size: 15px;
    letter-spacing: -.01em;
}

/* The outlined circle beside each panel heading picks up the theme */
body.skin-purple .tw-border-2.tw-rounded-full.tw-w-10.tw-h-10 {
    border-color: var(--dt-purple-100, #EADDFD);
    background: var(--dt-purple-50, #F5EFFE);
    color: var(--dt-purple-700, #7C3AED);
    border-radius: 11px;
}

/* Empty chart placeholders read as calm, not broken */
body.skin-purple .tw-border-dashed.tw-bg-gray-50 {
    background: #FAFAFD;
    border-color: var(--dash-line);
    border-radius: var(--dash-radius);
}

/* ------------------------------------------------------------------
   4. Small screens
   ------------------------------------------------------------------ */
@media (max-width: 767px) {
    body.skin-purple .theme-header-bg:not(.no-print) { padding-bottom: 36px !important; }
    body.skin-purple .dash-stat-grid > .tw-ring-1.tw-ring-gray-200 .tw-flex-1 > p + p { font-size: 1.05rem; }
}

@media (prefers-reduced-motion: reduce) {
    body.skin-purple .dash-stat-grid > .tw-ring-1.tw-ring-gray-200 { transition: none; }
    body.skin-purple .dash-stat-grid > .tw-ring-1.tw-ring-gray-200:hover { transform: none; }
}

/* ------------------------------------------------------------------
   The band under the second stat row
   ------------------------------------------------------------------ */
/* The second grid sits on a decorative two-row layer: the theme gradient
   above, a light grey block below. That block is what shows as a pale
   horizontal shape running under the cards -- the header colour stops
   half way through the grid and grey takes over, which reads as a stray
   panel rather than as the page.

   Made transparent so the gradient behind it carries through. The node
   is left in place: it is what gives the layer its two rows, and
   removing it would collapse the grid it belongs to. */
/* Transparent was not enough: the layer sits on the page, so clearing the
   grey simply let the page's own light canvas through and the band stayed
   where it was, a shade different.

   The grey half is removed from the layout instead and the gradient half
   stretched across both rows, so the strip carries the same colour as the
   rest of the block rather than a second one that has to be matched. */
body.skin-purple .theme-header-bg + .tw-bg-gray-100 {
    display: none;
}

body.skin-purple .theme-header-bg:has(+ .tw-bg-gray-100) {
    grid-row: 1 / -1;
}

/* ------------------------------------------------------------------
   Air between the cards and the due tables
   ------------------------------------------------------------------ */
/* The due list began immediately under the last card, so the two read as
   one block and the eye had nothing to tell it the section had changed.

   MARGIN, NOT PADDING, and the difference matters here. Padding would add
   the space INSIDE one of the two sections, and the card section is sitting
   on a decorative background layer -- so padding there would stretch that
   coloured panel down into the gap and put the band back. Margin is space
   BETWEEN two things and belongs to neither, which is exactly what a gap
   between sections is.

   It goes on the first due panel rather than under the cards because the
   thing being pushed away should own the distance: a section that is moved
   down carries its own clearance wherever it is used, while a margin under
   the cards would have to be repeated by anything else placed after them. */
body.skin-purple .due-panel:first-of-type {
    margin-top: 26px;
}

/* ------------------------------------------------------------------
   The notice ticker
   ------------------------------------------------------------------ */
/* It takes the gap between the sidebar buttons and the account controls, and
   the flex line is the whole story.

   The base size must be 0, not auto. A flex item's automatic base is its own
   content width, and this strip's content is always wider than the screen, so
   `auto` hands it an enormous base -- and flex shares out the shortfall in
   proportion to those bases. The buttons on the right lose a few hundred
   pixels, wrap onto a second line (they are allowed to wrap), and the row
   grows past the bar's fixed 60px and is clipped. With a base of 0 the strip
   asks for no width of its own and takes only what is left over, so nothing
   else is ever squeezed.

   min-width: 0 then lets it shrink below its content rather than overflow,
   and the height stays under the 36px the bar's padding leaves for content. */
.header-ticker {
    position: relative;
    flex: 1 1 0%;
    min-width: 0;
    display: flex;
    align-items: center;
    /* 36 is the ceiling: the bar keeps 60px with 12px of padding above and
       below, so anything taller grows it. */
    height: 36px;
    overflow: hidden;
    border-radius: 8px;
    /* A tinted chip rather than a wash. The navbar is white, so a white wash
       is nothing at all, and the strip needs a ground of its own to sit on
       whatever the bar behind it turns out to be. */
    background: #F4F0FD;
    border: 1px solid #E4DAFA;
    /* Text that simply stopped at the edge would read as cut off mid-word.
       Fading it out says "there is more" instead. */
    /* A short fade, not a long one. It is there so text does not look chopped
       off at the edge, and every pixel beyond that is a word somebody is
       trying to read at half strength. */
    -webkit-mask-image: linear-gradient(to right, transparent, #000 14px, #000 calc(100% - 14px), transparent);
    mask-image: linear-gradient(to right, transparent, #000 14px, #000 calc(100% - 14px), transparent);
}

/* The bar is a fixed 60px from lg up. Anything that makes its contents taller
   is therefore clipped rather than shown, and clipped is what "the header
   broke" looks like: half a button on one line, the rest cut off. The base of
   0 above should mean nothing ever gets taller, but a fixed height turns any
   mistake into a broken-looking page instead of a slightly untidy one, so the
   bar is allowed to grow and keeps 60px only as its floor. */
@media (min-width: 992px) {
    .theme-header-bg:has(.header-ticker) {
        height: auto;
        min-height: 60px;
    }
}

/* Below lg there is no gap to sit in -- the bar is buttons end to end -- so
   the strip takes a line of its own underneath them rather than disappearing.
   A phone owner needs these more than a desk does, not less. */
@media (max-width: 991px) {
    .theme-header-bg .tw-flex:has(> .header-ticker) { flex-wrap: wrap; }

    .header-ticker {
        order: 10;
        /* Shrinkable on purpose. The wrap above depends on :has(); if a
           browser ever ignores that rule, a basis of 100% that could not
           shrink would push the buttons off the end of the bar. This way the
           worst case is a narrower strip, not a broken header. */
        flex: 1 1 100%;
        margin-top: 8px;
    }
}

.header-ticker-track {
    display: flex;
    flex: 0 0 auto;
    width: max-content;
    animation-name: header-ticker-scroll;
    animation-timing-function: linear;
    animation-iteration-count: infinite;
    /* The pace is handed in per render, as a custom property rather than as
       animation-duration itself, so the reduced-motion rule below can do
       arithmetic on it instead of having to restate it. */
    animation-duration: var(--ticker-seconds, 40s);
}

/* Slide by exactly one copy's width and the next copy lands where the last
   one started, so the reset is invisible. The number is handed in per render
   because the number of copies is: it is whatever it took to make the strip
   wider than the bar. */
@keyframes header-ticker-scroll {
    from { transform: translateX(0); }
    to { transform: translateX(var(--ticker-shift, -50%)); }
}

/* Reading a moving line is the one thing this design makes hard, and a moving
   link cannot be clicked at all. Both are one hover away from fixed. */
.header-ticker:hover .header-ticker-track,
.header-ticker:focus-within .header-ticker-track {
    animation-play-state: paused;
}

/* It keeps moving for everyone, which was asked for explicitly. For anyone who
   has asked the system for less motion it runs at a third of the speed rather
   than stopping -- the gentlest reading of "always scrolling". */
@media (prefers-reduced-motion: reduce) {
    .header-ticker-track { animation-duration: calc(var(--ticker-seconds, 40s) * 3); }
}

.header-ticker-run {
    display: flex;
    align-items: center;
    flex: 0 0 auto;
}

.header-ticker-item {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 0 26px;
    font-size: 15px;
    font-weight: 600;
    white-space: nowrap;
    /* Dark on the light chip. Read in passing, at a glance, by somebody in
       the middle of doing something else -- full strength, because there is
       nothing to be gained by dimming it and a word to be lost. */
    color: #33235C;
    text-decoration: none;
}

a.header-ticker-item:hover,
a.header-ticker-item:focus {
    color: #1E1338;
    text-decoration: underline;
}

/* Urgency is carried mostly by the icon, so the sentence keeps one colour it
   is properly legible in. The worst tone takes the text as well, because on a
   light ground red type is readable -- which it was not on the dark bar this
   strip used to be designed for. */
.header-ticker-icon {
    width: 18px;
    height: 18px;
    flex: 0 0 auto;
    color: #2563EB;
}

.header-ticker-item.is-warn .header-ticker-icon { color: #B45309; }

.header-ticker-item.is-urgent {
    font-weight: 700;
    color: #B91C1C;
}

.header-ticker-item.is-urgent .header-ticker-icon { color: #DC2626; }

@media print {
    .header-ticker { display: none !important; }
}

/* ------------------------------------------------------------------
   Decorative POS hardware -- dashboard banner and till screen only
   ------------------------------------------------------------------ */
/* The layer never takes part in layout and never takes a click. On the till
   every click is a sale, and furniture that can swallow one is worse than no
   furniture at all. */
.pos-decor {
    pointer-events: none;
    user-select: none;
    overflow: hidden;
    z-index: 0;
}

/* Placement is carried per icon as custom properties, so one rule draws all of
   them and moving a piece is editing a number in the Blade file. */
.pos-decor svg {
    position: absolute;
    left: var(--x);
    top: var(--y);
    width: var(--s);
    height: var(--s);
    transform: translate(-50%, -50%) rotate(var(--r, 0deg));
}

/* Both hosts have to be positioned for the layer inside them to have anything
   to be absolute against. */
.dash-decor-host,
.pos-decor-host {
    position: relative;
}

.pos-decor--banner {
    position: absolute;
    inset: 0;
    color: #FFFFFF;
    /* Raised from .07, which was invisible in practice. That number was set
       against a preview banner lighter than the real one -- on the purple the
       dashboard actually uses, white at 7% does not clear the background. */
    opacity: .16;
}

/* On the till they sit inside the two panels rather than behind the page.
   Behind the page they could not be seen at all: the till is white panels edge
   to edge and they cover everything under them. */
.pos-decor--cart,
.pos-decor--column,
.pos-decor--products {
    position: absolute;
    inset: 0;
    color: #4A35A0;
    opacity: .11;
}

/* In the sidebar, behind the lower half of the menu. White, because the
   sidebar is dark purple (--dt-sidebar, #2A0A4A) whatever the aside utility
   class says -- the theme overrides tw-bg-white. The first attempt drew these
   in dark purple on dark purple and they were, predictably, invisible.

   The faintest of the four: a menu label has to win every time. */
.pos-decor--sidebar {
    position: absolute;
    inset: 0;
    color: #FFFFFF;
    opacity: .06;
}

/* Off below md. A phone has no room to spare behind the content, and on the
   till it is a working screen at arm's length rather than something anybody is
   admiring. */
@media (max-width: 767px) {
    .pos-decor { display: none; }
}

@media print {
    .pos-decor { display: none !important; }
}


/* ------------------------------------------------------------------
   9. Contact header — the card above a customer's or supplier's ledger
   ------------------------------------------------------------------
   Deliberately NOT the dashboard's stat tile. That tile carries a 129px
   min-height because it holds four big KPIs; a contact has three to seven
   smaller figures, and reusing it made a header taller than the ledger it
   introduces. Same design language — same radius, ink, muted grey, micro-caps
   label, semantic accent rail — at the size this content wants.

   Not scoped to body.skin-purple. The rest of this file is presentation over
   a working layout, so switching theme simply turns the polish off. Here the
   layout IS these rules: without them the figures fall into a single unstyled
   column, so they have to apply whatever theme the shop has chosen. */

.contact-header__identity {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    margin-bottom: 14px;
}

.contact-header__avatar {
    flex: 0 0 auto;
    width: 44px;
    height: 44px;
    border-radius: 11px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: #EDE9FE;
    color: #6D28D9;
    font-size: 18px;
}

.contact-header__name {
    min-width: 0;
}

.contact-header__name h3 {
    margin: 0 0 4px;
    font-size: 1.25rem;
    font-weight: 700;
    letter-spacing: -.01em;
    color: var(--dash-ink, #14181A);
    /* A business name can be long and there is a fixed column to sit in */
    overflow-wrap: anywhere;
}

.contact-header__badge,
.contact-header__ref {
    display: inline-block;
    padding: 2px 8px;
    border-radius: 999px;
    font-size: 10.5px;
    font-weight: 600;
    letter-spacing: .03em;
    text-transform: uppercase;
    vertical-align: middle;
}

/* Customer and supplier are told apart at a glance, because on a "both"
   contact the figures below come in two sets and the reader needs to know
   which half of the page they are in. */
.contact-header__badge--customer { background: #DBEAFE; color: #1D4ED8; }
.contact-header__badge--supplier { background: #DCFCE7; color: #15803D; }
.contact-header__badge--both     { background: #EDE9FE; color: #6D28D9; }
.contact-header__badge--lead     { background: #FEF3C7; color: #B45309; }

.contact-header__ref {
    background: #F1F5F9;
    color: var(--dash-muted, #6B7280);
    margin-left: 4px;
}

/* ---- The contact's own details ---------------------------------- */

.contact-header__facts {
    margin: 0;
}

.contact-header__facts dt {
    font-size: 10.5px;
    font-weight: 600;
    letter-spacing: .03em;
    text-transform: uppercase;
    color: var(--dash-muted, #6B7280);
    margin-top: 10px;
}

.contact-header__facts dt:first-child {
    margin-top: 0;
}

.contact-header__facts dt i {
    width: 14px;
    text-align: center;
    margin-right: 3px;
    opacity: .7;
}

.contact-header__facts dd {
    margin: 1px 0 0;
    font-size: 13.5px;
    color: var(--dash-ink, #14181A);
    overflow-wrap: anywhere;
}

.contact-header__facts dd a {
    color: inherit;
}

/* ---- The account summary ------------------------------------------
   The ledger's own shape, kept because it is the better one here. Five to
   eight labelled amounts read down a column far faster than across a grid of
   cards, and the row that matters can carry weight at the bottom the way the
   last line of a bill does.

   The heading was .blue-heading, borrowed from the printed ledger so the two
   could not drift. They are allowed to differ after all, and they should: this
   one is chrome inside a purple application and belongs to it, while the
   ledger's is the masthead of a document that gets printed and posted. Same
   words, two different jobs.

   --dt-purple-800 is the banner's deep purple, so the card's heading and the
   top of the dashboard are the same colour rather than two purples. */

.contact-summary {
    border: 1px solid var(--dash-line, #E7E7F0);
    border-radius: var(--dash-radius, 12px);
    overflow: hidden;
}

.contact-summary__title {
    margin: 0;
    padding: 10px 16px;
    font-size: 1.1rem;
    font-weight: 700;
    letter-spacing: -.01em;
    background: var(--dt-purple-800, #3B1063);
    color: #FFFFFF;
}

.contact-summary__table {
    width: 100%;
    margin: 0;
    background: #FFFFFF;
}

.contact-summary__table th,
.contact-summary__table td {
    padding: 9px 16px;
    border-bottom: 1px solid var(--dash-line, #E7E7F0);
    vertical-align: middle;
}

.contact-summary__table tr:last-child th,
.contact-summary__table tr:last-child td {
    border-bottom: 0;
}

.contact-summary__table th {
    font-weight: 500;
    font-size: 13.5px;
    color: var(--dash-muted, #6B7280);
    text-align: start;
}

.contact-summary__table td {
    font-size: 14.5px;
    font-weight: 600;
    color: var(--dash-ink, #14181A);
    text-align: end;
    white-space: nowrap;
}

/* The bottom line, given the weight the bottom line of a bill has. */
.contact-summary__due th,
.contact-summary__due td {
    background: #F8FAFC;
    font-weight: 700;
    font-size: 15px;
}

.contact-summary__due th {
    color: var(--dash-ink, #14181A);
}

/* Red only when something is actually owed. Painting a settled account as a
   warning is how people learn to ignore the warning colour. */
.contact-summary__due.is-owing td {
    color: #B91C1C;
}
/* ---- Actions ------------------------------------------------------ */

.contact-header__actions {
    display: flex;
    flex-wrap: wrap;
    justify-content: flex-end;
    gap: 8px;
    margin-top: 12px;
}

/* Under about 992px the two halves stack and the summary takes the full
   width, which it is happy to do -- it is a column of rows either way. */
@media (max-width: 991px) {
    .contact-header__identity {
        margin-top: 4px;
    }

    .contact-summary {
        margin-top: 16px;
    }
}

/* Printing: this header sits above the ledger, which is the thing being
   printed. Keep it readable in ink rather than reproducing tinted chips. */
@media print {
    .contact-header__avatar,
    .contact-header__badge,
    .contact-header__ref,
    .contact-summary__due th,
    .contact-summary__due td {
        background: transparent !important;
        color: #000 !important;
    }
}

/* ------------------------------------------------------------------
   10. The ledger's letterhead — printed, not shown
   ------------------------------------------------------------------
   The business address, the PARTNER LEDGER title, the contact's details and
   the Account Summary. On screen every one of those is already in the card
   above the tab, so the page repeated itself inside a single scroll. In print
   and in the emailed PDF it is the only copy there is: a ledger that leaves
   the building has to say who issued it and who it is about.

   @media screen, not .no-print. The two say opposite things and only this one
   is true here.

   The PDF path does not load this stylesheet at all -- it links css/app.css by
   itself -- so nothing here can reach it. The rule is confined to the browser
   window on purpose. */
@media screen {
    .ledger-letterhead {
        display: none;
    }
}

/* ------------------------------------------------------------------
   11. The ledger's toolbar
   ------------------------------------------------------------------
   Two fields that change what you are looking at, two buttons that send it
   somewhere. Flex rather than bootstrap columns so the fields keep a sensible
   width instead of a twelfth-of-the-page one, and so the buttons can sit on
   the same baseline as the inputs rather than floating at the top of the row
   because they have no label above them. */

.ledger-toolbar {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: 12px 16px;
    padding: 14px 16px;
    margin-bottom: 4px;
    border: 1px solid var(--dash-line, #E7E7F0);
    border-radius: var(--dash-radius, 12px);
    background: #FBFBFD;
}

.ledger-toolbar__field {
    flex: 1 1 220px;
    /* Wide enough for a date range on one line, narrow enough that two of them
       plus the buttons still fit across a laptop. */
    max-width: 300px;
    min-width: 0;
    margin: 0;
}

.ledger-toolbar__field label {
    display: block;
    margin-bottom: 4px;
    font-size: 10.5px;
    font-weight: 600;
    letter-spacing: .03em;
    text-transform: uppercase;
    color: var(--dash-muted, #6B7280);
}

/* select2 replaces the select with its own markup and defaults to the width of
   its content, which is how a location box ends up narrower than its label. */
.ledger-toolbar__field .select2-container {
    width: 100% !important;
}

/* The two buttons go to the far end, and stay together when the row wraps. */
.ledger-toolbar__actions {
    margin-inline-start: auto;
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

.ledger-toolbar__actions .btn {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    /* Matching the height of a .form-control beside it, so the row reads as
       one line rather than as controls at three different heights. */
    height: 34px;
    padding: 0 14px;
    border-radius: 8px;
}

/* Under about 640px the labels are the first thing worth losing: the icons are
   distinct and the tooltip is still there. */
@media (max-width: 640px) {
    .ledger-toolbar__field {
        max-width: none;
    }

    .ledger-toolbar__actions {
        margin-inline-start: 0;
    }

    .ledger-toolbar__actions .btn span {
        display: none;
    }

    .ledger-toolbar__actions .btn {
        padding: 0 12px;
    }
}

/* The toolbar is a control, not content. It has no place on the printed
   ledger. */
@media print {
    .ledger-toolbar {
        display: none;
    }
}

/* ------------------------------------------------------------------
   12. The guarantor on an instalment customer
   ------------------------------------------------------------------
   Set apart from the customer's own details rather than continuing the same
   list, because these are a different person's name, phone and address. Run
   together, somebody chasing a late instalment could dial the wrong number
   with the right intention. */

.contact-guarantor {
    margin-top: 16px;
    padding: 12px 14px;
    border: 1px solid var(--dash-line, #E7E7F0);
    border-inline-start: 3px solid var(--dt-purple-300, #C4A2F8);
    border-radius: var(--dash-radius, 12px);
    background: #FBFAFE;
}

.contact-guarantor__title {
    margin: 0 0 8px;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--dt-purple-800, #3B1063);
}

.contact-guarantor__title i {
    margin-inline-end: 4px;
    opacity: .8;
}

/* The rows inside reuse .contact-header__facts, so the two blocks read as one
   family — same label size, same spacing — while the frame keeps them apart. */
.contact-guarantor .contact-header__facts dt:first-child {
    margin-top: 0;
}

/* ------------------------------------------------------------------
   Stat tiles: one headline, three compact
   ------------------------------------------------------------------
   The four tiles in each row were identical, so nothing in the row was
   the thing to look at first, and each carried a 129px min-height for
   content that needs about sixty -- roughly half of every tile was
   empty.

   The first tile of each row becomes the headline: full height of the
   block, a bigger number, and the context strip underneath. The other
   three stack beside it as compact rows, which is what buys back the
   height the headline spends.

   Layout only -- no tile was added, removed or reordered. The rule
   applies from xl up, where the row was four across; below that the
   Tailwind classes still stack them and nothing here interferes.
   ------------------------------------------------------------------ */
@media (min-width: 1280px) {
    body.skin-purple .dash-stat-grid {
        grid-template-columns: 1fr 1fr;
        align-items: stretch;
        /* Tighter than the 20px between the two columns: these three rows are
           one group of related figures, and the headline beside them has to
           come out the same height as all three put together. */
        row-gap: 14px;
    }

    /* Column one, all three rows of it. */
    body.skin-purple .dash-stat-grid > .tw-ring-1.tw-ring-gray-200:first-child {
        grid-row: span 3;
        min-height: 0;
        display: flex;
        flex-direction: column;
        justify-content: center;
    }

    body.skin-purple .dash-stat-grid > .tw-ring-1.tw-ring-gray-200:first-child > div {
        padding: 14px 20px;
    }

    /* The label carries a 2.5em min-height so four equal tiles line up. The
       headline is not one of four equal tiles, and that reserved second line
       was pushing it taller than the three rows beside it -- which left the
       stack stretched and a band of empty card under the sparkline. */
    body.skin-purple .dash-stat-grid > .tw-ring-1.tw-ring-gray-200:first-child .tw-text-sm.tw-text-gray-500 {
        min-height: 0;
    }

    /* The number carries the emphasis, not a heavier border or a louder
       colour: those would compete with the accent rail that already says
       what kind of figure this is. */
    body.skin-purple .dash-stat-grid > .tw-ring-1.tw-ring-gray-200:first-child .tw-flex-1 > p + p {
        font-size: clamp(1.5rem, 2.1vw, 2rem);
    }

    body.skin-purple .dash-stat-grid > .tw-ring-1.tw-ring-gray-200:first-child .tw-rounded-full.tw-shrink-0 {
        width: 52px;
        height: 52px;
    }

    /* The other three: a row each, sized to their content. */
    body.skin-purple .dash-stat-grid > .tw-ring-1.tw-ring-gray-200:not(:first-child) {
        min-height: 0;
    }

    body.skin-purple .dash-stat-grid > .tw-ring-1.tw-ring-gray-200:not(:first-child) > div {
        padding: 7px 14px;
    }

    body.skin-purple .dash-stat-grid > .tw-ring-1.tw-ring-gray-200:not(:first-child) .tw-rounded-full.tw-shrink-0 {
        width: 28px;
        height: 28px;
        border-radius: 8px;
    }

    body.skin-purple .dash-stat-grid > .tw-ring-1.tw-ring-gray-200:not(:first-child) .tw-rounded-full.tw-shrink-0 svg {
        width: 15px;
        height: 15px;
    }

    /* Label and figure share a line, which is the whole reason these fit
       three-to-a-headline. The label's min-height was there to keep four
       equal tiles level; these are not four equal tiles. */
    body.skin-purple .dash-stat-grid > .tw-ring-1.tw-ring-gray-200:not(:first-child) .tw-flex-1 {
        display: flex;
        align-items: baseline;
        justify-content: space-between;
        gap: 10px;
    }

    body.skin-purple .dash-stat-grid > .tw-ring-1.tw-ring-gray-200:not(:first-child) .tw-text-sm.tw-text-gray-500 {
        min-height: 0;
        display: block;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
    }

    body.skin-purple .dash-stat-grid > .tw-ring-1.tw-ring-gray-200:not(:first-child) .tw-flex-1 > p + p {
        margin-top: 0;
        font-size: .95rem;
        white-space: nowrap;
    }
}

/* ------------------------------------------------------------------
   The context strip under a headline tile
   ------------------------------------------------------------------ */
.dash-trend {
    display: flex;
    align-items: center;
    gap: 7px;
    margin-top: 12px;
    padding-top: 10px;
    border-top: 1px dashed #E9EDF3;
    font-size: 11.5px;
    font-weight: 600;
    color: var(--dash-muted, #64748B);
    line-height: 1;
}

.dash-trend[hidden] { display: none; }

.dash-trend__delta { font-weight: 700; }
.dash-trend.is-up   .dash-trend__delta { color: #15803D; }
.dash-trend.is-down .dash-trend__delta { color: #B91C1C; }
.dash-trend.is-flat .dash-trend__delta { color: var(--dash-muted, #64748B); }

/* ------------------------------------------------------------------
   The chart beside the figure
   ------------------------------------------------------------------
   A headline tile is half the row wide, and its content -- icon, label,
   number -- fills maybe half of that, so the right of the card was
   blank. The trend was already being drawn; it was just drawn 62px wide
   in the corner. Given the space instead, it becomes the thing that
   fills it, which beats decoration: it is the same data as the number
   above it, in the one form a number cannot take.
   ------------------------------------------------------------------ */
.dash-spark {
    position: absolute;
    inset-block: 16px;
    inset-inline-end: 18px;
    width: 42%;
    max-width: 260px;
    /* Behind the figure in every sense: it must never take a click meant
       for the tile, and a long value has to run over the chart rather
       than under it. An absolutely positioned element paints above
       in-flow content by default, so both need saying. */
    pointer-events: none;
    z-index: 0;
    color: #94A3B8;
}

body.skin-purple .dash-stat-grid > .tw-ring-1.tw-ring-gray-200:first-child .tw-flex,
body.skin-purple .dash-stat-grid > .tw-ring-1.tw-ring-gray-200:first-child .dash-trend {
    position: relative;
    z-index: 1;
}

.dash-spark[hidden] { display: none; }

.dash-spark svg {
    width: 100%;
    height: 100%;
    display: block;
    /* The stroke sits on the edge of the box at a peak or a trough;
       without this it would be clipped in half. */
    overflow: visible;
}

/* The fill is what makes it read as a quantity rather than a squiggle,
   and it stays faint so the number is still the loudest thing here. */
.dash-spark__area { fill: currentColor; opacity: .13; }
.dash-spark__line { opacity: .9; }

.dash-spark.is-up   { color: #16A34A; }
.dash-spark.is-down { color: #DC2626; }
.dash-spark.is-flat { color: #94A3B8; }

/* Only the headline tile has the room for it. Below xl every tile is a
   stacked full-width row, and a chart behind the text would be noise. */
@media (max-width: 1279px) {
    .dash-spark { display: none !important; }
}

/* ------------------------------------------------------------------
   A headline tile with nothing to chart
   ------------------------------------------------------------------
   Three tiles end up here: Current Stock Value, which is a running
   balance and has no daily series at all; any tile whose range is too
   short to join two points; and -- the one that actually turned up --
   a shop with a quiet day, whose series is all zeros.

   The right-hand half is reserved for a chart. With no chart in it that
   half is simply a hole, which is what the tile looked like on a day
   with no sales. The content spreads into it instead: the number moves
   to the middle of the card and the card reads as a wide tile rather
   than a half-empty one.

   Driven by a class from render_stat_trend() rather than by :has(),
   because the third tile never calls that function at all and so has no
   chart element to match on.
   ------------------------------------------------------------------ */
@media (min-width: 1280px) {
    body.skin-purple .dash-stat-grid > .tw-ring-1.tw-ring-gray-200:first-child:not(.dash-has-chart) .tw-flex,
    body.skin-purple .dash-stat-grid > .tw-ring-1.tw-ring-gray-200:first-child:not(.dash-has-chart) .dash-trend {
        justify-content: center;
    }

    /* The figure grows into the space the chart is not using. */
    body.skin-purple .dash-stat-grid > .tw-ring-1.tw-ring-gray-200:first-child:not(.dash-has-chart) .tw-flex-1 {
        flex: 0 1 auto;
    }
}

/* Below xl the headline tile is just another tile in a stacked column,
   and the strip goes with it. */
@media (max-width: 1279px) {
    .dash-trend { margin-top: 10px; padding-top: 8px; }
}

/* ==================================================================
   Dashboard: greeting, headline figures, trend, key figures, actions
   ==================================================================
   The page used to open with twelve identical tiles. It now opens with
   a greeting, four figures, the trend beside the other eight, and the
   handful of things a shop starts from here.

   Written against the light card surface the dashboard already uses,
   over the purple banner it already has. The sidebar is untouched.
   ================================================================== */

/* ---------- greeting ---------- */
.dash-greeting {
    display: flex;
    align-items: center;
    gap: 18px;
    flex-wrap: wrap;
    padding: 14px 18px;
    margin-bottom: 4px;
    border-radius: 16px;
    background: linear-gradient(120deg, rgba(255,255,255,.16), rgba(255,255,255,.07));
    border: 1px solid rgba(255,255,255,.18);
}

.dash-greeting__hello { display: flex; align-items: center; gap: 14px; min-width: 0; }
.dash-greeting__wave { font-size: 30px; line-height: 1; flex: 0 0 auto; }
.dash-greeting__text { min-width: 0; }

.dash-greeting__title {
    margin: 0;
    /* A shade smaller than it was: a full name is longer than a first name,
       and the line has a quote and a clock to share the row with. */
    font-size: 17px;
    font-weight: 800;
    letter-spacing: -.01em;
    color: #FFFFFF;
}

.dash-greeting__sub { margin: 2px 0 0; font-size: 12px; color: rgba(255,255,255,.78); }

/* The quote takes the middle only when there is a middle to take. */
.dash-greeting__quote {
    flex: 1 1 220px;
    min-width: 0;
    margin: 0;
    text-align: center;
    font-size: 13px;
    font-style: italic;
    color: rgba(255,255,255,.80);
}

.dash-greeting__clock {
    display: flex;
    align-items: center;
    gap: 10px;
    flex: 0 0 auto;
    padding: 9px 14px;
    border-radius: 12px;
    background: rgba(255,255,255,.14);
    border: 1px solid rgba(255,255,255,.20);
    color: #FFFFFF;
    /* Read, not selected: dragging past it while reaching for the date
       filter should not highlight it. */
    user-select: none;
    cursor: default;
}

.dash-greeting__clock-icon { color: rgba(255,255,255,.75); flex: 0 0 auto; }
.dash-greeting__date { font-size: 12.5px; font-weight: 600; color: rgba(255,255,255,.85); }

.dash-greeting__time {
    /* Tabular figures, or the row twitches a pixel wider every second as
       the digits change. */
    font-variant-numeric: tabular-nums;
    font-feature-settings: "tnum" 1;
    font-size: 16px;
    font-weight: 800;
    letter-spacing: .01em;
}

@media (max-width: 767px) {
    .dash-greeting { gap: 12px; }
    .dash-greeting__quote { display: none; }
    .dash-greeting__title { font-size: 15px; }
}

/* ---------- headline figures ---------- */
.dash-headline {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 16px;
    margin-top: 18px;
}

.dash-headline__card {
    display: flex;
    align-items: flex-start;
    gap: 14px;
    padding: 16px 18px;
    background: #FFFFFF;
    border-radius: 14px;
    border: 1px solid #E7E4F0;
    box-shadow: 0 1px 2px rgba(20,24,26,.05), 0 10px 26px -20px rgba(20,24,26,.35);
    transition: transform .16s ease, box-shadow .16s ease;
}

.dash-headline__card:hover {
    transform: translateY(-2px);
    box-shadow: 0 1px 2px rgba(20,24,26,.05), 0 16px 34px -18px rgba(20,24,26,.45);
}

.dash-headline__icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 46px;
    height: 46px;
    border-radius: 13px;
    flex: 0 0 auto;
}

/* One hue per figure, so a shop learns the row by shape and colour rather
   than by reading four labels every time. */
.dash-headline__card.is-sales    .dash-headline__icon { background: #DCFCE7; color: #16A34A; }
.dash-headline__card.is-purchase .dash-headline__icon { background: #FEE2E2; color: #DC2626; }
.dash-headline__card.is-profit   .dash-headline__icon { background: #DBEAFE; color: #2563EB; }
.dash-headline__card.is-stock    .dash-headline__icon { background: #EDE9FE; color: #7C3AED; }

.dash-headline__body { min-width: 0; flex: 1 1 auto; }

.dash-headline__label {
    margin: 0;
    font-size: 12px;
    font-weight: 600;
    color: #64748B;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.dash-headline__value {
    margin: 2px 0 0;
    font-size: clamp(1.15rem, 1.6vw, 1.5rem);
    font-weight: 800;
    letter-spacing: -.02em;
    color: #0F172A;
    white-space: nowrap;
}

@media (max-width: 1279px) { .dash-headline { grid-template-columns: repeat(2, minmax(0,1fr)); } }
@media (max-width: 575px)  { .dash-headline { grid-template-columns: minmax(0,1fr); } }

/* ---------- trend + key figures ---------- */
.dash-split {
    display: grid;
    grid-template-columns: minmax(0, 1.55fr) minmax(0, 1fr);
    gap: 16px;
    padding: 18px 20px 0;
}

@media (max-width: 1279px) { .dash-split { grid-template-columns: minmax(0,1fr); } }

.dash-panel {
    background: #FFFFFF;
    border-radius: 14px;
    border: 1px solid #E7E4F0;
    box-shadow: 0 1px 2px rgba(20,24,26,.05), 0 10px 26px -20px rgba(20,24,26,.35);
    padding: 16px 18px;
}

.dash-panel__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    flex-wrap: wrap;
    margin-bottom: 12px;
}

.dash-panel__title {
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 0;
    font-size: 15px;
    font-weight: 800;
    color: #0F172A;
}
.dash-panel__title svg { color: #7C3AED; }

.dash-panel__link {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font-size: 12.5px;
    font-weight: 700;
    color: #7C3AED;
    text-decoration: none;
}
.dash-panel__link:hover { color: #5B21B6; text-decoration: none; }

/* range buttons */
.dash-range { display: inline-flex; gap: 4px; padding: 3px; background: #F4F2FA; border-radius: 10px; }

.dash-range__btn {
    border: 0;
    background: transparent;
    padding: 5px 11px;
    border-radius: 8px;
    font-size: 12px;
    font-weight: 700;
    color: #64748B;
    cursor: pointer;
    transition: background-color .15s ease, color .15s ease;
}
.dash-range__btn:hover { color: #0F172A; }
.dash-range__btn.is-active { background: #7C3AED; color: #FFFFFF; }

.dash-chart { position: relative; min-height: 230px; }

/* key figures list */
.dash-figures__list { list-style: none; margin: 0; padding: 0; }

.dash-figures__row {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 8px 2px;
    border-bottom: 1px solid #F1EFF7;
}
.dash-figures__row:last-child { border-bottom: 0; }

.dash-figures__icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    border-radius: 8px;
    flex: 0 0 auto;
}
.dash-figures__icon.is-green  { background: #DCFCE7; color: #16A34A; }
.dash-figures__icon.is-amber  { background: #FEF3C7; color: #D97706; }
.dash-figures__icon.is-rose   { background: #FEE2E2; color: #DC2626; }
.dash-figures__icon.is-indigo { background: #E0E7FF; color: #4F46E5; }
.dash-figures__icon.is-orange { background: #FFEDD5; color: #EA580C; }
.dash-figures__icon.is-sky    { background: #E0F2FE; color: #0284C7; }

.dash-figures__label {
    flex: 1 1 auto;
    min-width: 0;
    font-size: 13px;
    font-weight: 600;
    color: #475569;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.dash-figures__value {
    font-size: 13.5px;
    font-weight: 800;
    color: #0F172A;
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
}

/* ---------- quick actions ---------- */
.dash-actions { padding: 18px 20px 0; }

.dash-actions__title {
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 0 0 10px;
    font-size: 15px;
    font-weight: 800;
    color: #0F172A;
}
.dash-actions__title svg { color: #7C3AED; }

.dash-actions__row {
    display: grid;
    grid-template-columns: repeat(6, minmax(0, 1fr));
    gap: 12px;
}

.dash-action {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 8px;
    padding: 14px 10px;
    border-radius: 13px;
    background: #FFFFFF;
    border: 1px solid #E7E4F0;
    text-decoration: none;
    font-size: 12.5px;
    font-weight: 700;
    color: #334155;
    text-align: center;
    transition: transform .15s ease, box-shadow .15s ease, border-color .15s ease;
}
.dash-action:hover {
    transform: translateY(-2px);
    box-shadow: 0 10px 24px -14px rgba(20,24,26,.5);
    text-decoration: none;
    color: #0F172A;
}

.dash-action__icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    border-radius: 12px;
}
.dash-action.is-green  .dash-action__icon { background: #DCFCE7; color: #16A34A; }
.dash-action.is-indigo .dash-action__icon { background: #E0E7FF; color: #4F46E5; }
.dash-action.is-rose   .dash-action__icon { background: #FEE2E2; color: #DC2626; }
.dash-action.is-sky    .dash-action__icon { background: #E0F2FE; color: #0284C7; }
.dash-action.is-amber  .dash-action__icon { background: #FEF3C7; color: #D97706; }
.dash-action.is-violet .dash-action__icon { background: #EDE9FE; color: #7C3AED; }
.dash-action__label { line-height: 1.25; }

@media (max-width: 991px) { .dash-actions__row { grid-template-columns: repeat(3, minmax(0,1fr)); } }
@media (max-width: 575px) { .dash-actions__row { grid-template-columns: repeat(2, minmax(0,1fr)); } }

@media (prefers-reduced-motion: reduce) {
    .dash-headline__card, .dash-action { transition: none; }
}

/* ------------------------------------------------------------------
   Greeting: a light panel carrying the time of day
   ------------------------------------------------------------------
   The scene behind it is one of four drawings -- morning, afternoon,
   evening, night -- chosen on the server by the same decision that
   picks the words, so the picture can never say evening while the text
   says afternoon.

   Set through a custom property the blade fills in, rather than four
   background-image rules here. The file name is already worked out
   where the part of day is decided; repeating that mapping in CSS is
   how the two drift apart.

   These rules come after the ones above and deliberately replace the
   translucent-on-purple treatment: the panel is light now, so the text
   on it has to be dark.
   ------------------------------------------------------------------ */
.dash-greeting {
    position: relative;
    overflow: hidden;
    /* The drawing is scaled to the panel's height, so a short panel gives it
       almost no width -- at 55px the whole scene rendered narrower than the
       clock sitting on top of it and was never seen. This is the height that
       lets it read. */
    min-height: 92px;
    background-color: #EFEBFB;
    background-image: var(--dash-greeting-scene);
    /* Anchored right: the drawing is built with its subject on that side
       and fading out towards the middle, so the words keep a clean
       ground whatever the panel's width turns out to be. */
    background-repeat: no-repeat;
    background-position: right center;
    /* A fixed width rather than one derived from the height. Scaled by height
       the whole drawing came out 342px wide, the clock covers 258px of that,
       and the 84px left over was the deliberately faded edge -- so the scene
       was there and invisible. At this width its subject clears the clock. */
    background-size: 520px 100%;
    border: 1px solid rgba(124, 58, 237, .14);
}

/* Each part of day tints the panel itself, so the left half -- where
   the drawing has already faded out -- still belongs to the same
   picture. */
.dash-greeting.is-morning   { background-color: #FBEFE4; }
.dash-greeting.is-afternoon { background-color: #E8F1FC; }
.dash-greeting.is-evening   { background-color: #F3E7F3; }
.dash-greeting.is-night     { background-color: #E7E4F5; }

.dash-greeting__title { color: #1E1B3A; }
.dash-greeting__sub   { color: #55507A; }

.dash-greeting__quote {
    color: #4B4570;
    /* It sits over the fading edge of the drawing, so it gets a little
       weight to stay legible there. */
    font-weight: 600;
    text-shadow: 0 1px 0 rgba(255, 255, 255, .5);
}

.dash-greeting__clock {
    background: rgba(255, 255, 255, .78);
    border-color: rgba(124, 58, 237, .18);
    color: #1E1B3A;
    /* The clock lands on the busiest part of the drawing, so it needs a
       ground of its own rather than a tint of what is behind it. */
    backdrop-filter: blur(2px);
}

.dash-greeting__clock-icon { color: #7C3AED; }
.dash-greeting__date { color: #55507A; }
.dash-greeting__time { color: #1E1B3A; }

/* Narrow screens drop the quote already; below that the drawing is
   more texture than picture and the words need the whole width. */
@media (max-width: 575px) {
    .dash-greeting { background-image: none; }
}

/* ==================================================================
   Phones
   ==================================================================
   The dashboard was laid out for a desk and then allowed to stack. It
   works, but a shopkeeper checking the day's takings on a phone had to
   scroll past four tiles that were each mostly white space before
   reaching anything else.

   Everything below is spacing and proportion only. No figure, no
   value class, no chart and no table changes -- home.js fills the same
   elements it always did.
   ================================================================== */

/* ---------- the four headline figures ---------- */
/* Two across instead of one. At one per row the four of them took the
   whole of a phone screen before the chart began; at two they take
   half, and none of them is a long enough phrase or a big enough
   number to need a full width to itself.

   Stacked rather than icon-beside-text, because a 171px card split
   between a 46px icon and the words leaves the words nowhere to go --
   "Current Stock Value" was ellipsed to "Current Stock V…". */
@media (max-width: 575px) {
    .dash-headline {
        grid-template-columns: repeat(2, minmax(0, 1fr));
        gap: 10px;
        margin-top: 14px;
    }

    .dash-headline__card {
        flex-direction: column;
        align-items: stretch;
        gap: 9px;
        padding: 12px 13px;
        border-radius: 13px;
    }

    .dash-headline__icon {
        width: 34px;
        height: 34px;
        border-radius: 10px;
    }
    .dash-headline__icon svg {
        width: 19px;
        height: 19px;
    }

    /* The label wraps to a second line rather than being cut off. Two
       lines of 11.5px is cheaper than losing the end of the phrase --
       and the four cards share a row, so they end up the same height
       whether or not one of them wraps. */
    .dash-headline__label {
        white-space: normal;
        font-size: 11.5px;
        line-height: 1.3;
    }

    .dash-headline__value {
        font-size: 1.1rem;
        margin-top: 3px;
        /* A long figure breaks rather than widening the grid column and
           pushing the card out of the screen. */
        white-space: normal;
        overflow-wrap: anywhere;
    }

    .dash-trend {
        margin-top: 8px;
        padding-top: 7px;
        font-size: 10.5px;
        gap: 5px;
        /* "vs the previous 7 days" is a second line here rather than a
           reason for the card to be wider than half the screen. */
        flex-wrap: wrap;
        line-height: 1.35;
    }
}
