/* ===========================================================================
   style.css — Backline Ops books

   The palette is lifted straight off the emblem, so the app and the mark it
   carries look like one thing: slate for structure, steel for surfaces, the
   rust bar for the one thing on screen that wants attention.

   ⚠️ 16px MINIMUM ON EVERY INPUT. Anything smaller makes iOS Safari zoom the
   whole page in when the field is focused, and it never zooms back out. That
   is the proper fix for zoom-on-focus; disabling pinch-zoom is not.
   =========================================================================== */

:root{
  --navy:#26333F;
  --navy-deep:#1B2530;
  --slate:#3D5164;
  --slate-soft:#5C6B7A;
  --steel:#C9D2D8;
  --line:#DFE5EA;
  --wash:#F4F6F8;
  --paper:#FFFFFF;
  --rust:#C24E32;
  --rust-soft:#FBEDE6;
  --good:#1D6B43;
  --good-soft:#E6F4EC;
  --warn:#A8412A;
  --ink:#1B2530;
  --radius:13px;
  --shadow:0 1px 3px rgba(27,37,48,.07), 0 6px 20px rgba(27,37,48,.06);
  --tabbar:64px;
}

*{box-sizing:border-box}
html,body{margin:0;padding:0}
body{
  background:var(--wash);color:var(--ink);
  font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;
  font-size:15px;line-height:1.5;-webkit-text-size-adjust:100%;
  padding-bottom:calc(var(--tabbar) + env(safe-area-inset-bottom));
}
h1,h2,h3{margin:0;font-weight:800;letter-spacing:-.2px}
button{font-family:inherit}
a{color:var(--navy)}

.boot{display:flex;flex-direction:column;align-items:center;justify-content:center;
  min-height:70vh;gap:14px;color:var(--slate-soft)}

/* ── Sign in ─────────────────────────────────────────────────────────────*/
.signin{min-height:100vh;display:flex;flex-direction:column;align-items:center;
  justify-content:center;gap:18px;padding:32px 20px;text-align:center;
  background:radial-gradient(120% 90% at 50% 0%, #FFFFFF 0%, #F4F7F9 55%, #DFE6EC 100%)}
.signin img{width:132px;height:132px}
.signin h1{color:var(--ink);font-size:21px}
.signin p{color:var(--slate-soft);margin:0;font-size:14px;max-width:320px}
.whopick{display:flex;flex-wrap:wrap;gap:10px;justify-content:center;margin-top:4px}
/* ⛔ THE PUBLIC'S DOOR — a name typed, never a list offered. See the note on
   signDevice in worker.js for what this replaced and why.
   ⚠️ 16px ON THE INPUT IS NOT A STYLE CHOICE. Safari on iPhone zooms the whole
   page in on any focused field under 16px and never zooms back out, so the
   sign-in screen ends up scrolled sideways with the PIN pad off the edge. */
.whotype{display:flex;gap:8px;justify-content:center;flex-wrap:wrap;margin-top:4px}
.whotype input{padding:11px 16px;border-radius:999px;border:1px solid var(--line);
  background:var(--paper);color:var(--navy);font-weight:700;font-size:16px;
  text-align:center;width:190px;max-width:60vw}
.whotype input:focus{outline:none;border-color:var(--navy)}
.whotype button{padding:11px 20px;border-radius:999px;border:1px solid var(--navy);
  background:var(--navy);color:#F2F4F5;font-weight:700;font-size:15px;cursor:pointer}
.signin .whoname{color:var(--navy);font-weight:700;font-size:15px;display:flex;
  align-items:center;gap:8px;justify-content:center;flex-wrap:wrap}
.linkish{border:none;background:none;padding:0;color:var(--slate-soft);
  font-size:13px;font-weight:600;text-decoration:underline;cursor:pointer}
.who{padding:11px 20px;border-radius:999px;border:1px solid var(--line);background:var(--paper);
  color:var(--navy);font-weight:700;font-size:15px;cursor:pointer}
.who.on{background:var(--navy);color:#F2F4F5;border-color:var(--navy)}
.pinpad{display:grid;grid-template-columns:repeat(3,72px);gap:11px;margin-top:6px}
.pinpad button{height:60px;border-radius:14px;border:1px solid var(--line);background:var(--paper);
  color:var(--navy);font-size:23px;font-weight:700;cursor:pointer}
.pinpad button:active{background:#E8EDF1}
.pinpad button.wide{grid-column:span 1;font-size:15px}
.dots{display:flex;gap:11px;margin-top:4px;height:15px}
.dot{width:13px;height:13px;border-radius:50%;background:#C7D2DB}
.dot.on{background:var(--navy)}
/* ⚠️ `.signin .signerr`, NOT `.signerr`, AND THE EXTRA CLASS IS THE WHOLE POINT.
   The element is a <p> inside .signin, so `.signin p` (0,1,1) outranks a bare
   `.signerr` (0,1,0) and the error colour never applied — the one line that
   tells somebody their PIN was wrong has been rendering in the same muted grey
   as "Who is this?" all along. It was invisible as a bug because the muted
   colour was still legible; it just never looked like a problem.
   Found by screenshotting the screen rather than by reading the change. */
.signin .signerr{color:var(--warn);font-size:14px;min-height:20px;margin:0}

/* ── Shell ───────────────────────────────────────────────────────────────*/
.top{background:var(--paper);color:var(--ink);border-bottom:1px solid var(--line);padding:calc(env(safe-area-inset-top) + 14px) 18px 14px;
  display:flex;align-items:center;gap:12px;position:sticky;top:0;z-index:20}
.top img{width:34px;height:34px}
.top .name{font-weight:800;font-size:16px;letter-spacing:.2px}
.top .sub{color:var(--slate-soft);font-size:12px}
/* ★ THE TRADEMARK MARK. Same numbers as the new-store setup page, deliberately,
   so the mark looks like one mark rather than two that nearly match. Quiet by
   design: half height, raised, no extra tracking, slightly transparent. A
   full-size ™ next to a brand reads as shouting and this brand's tone is the
   opposite.
   ⚠️ letter-spacing:0 RESETS the .2px the wordmark carries. Tracking applies
   after the glyph too, so without this the ™ pushes a visible gap off the end
   of the name. */
.tm{font-size:.5em;vertical-align:super;letter-spacing:0;opacity:.7}
/* .top .right and .ghost styled the Hub → button, which is gone. Deleted
   rather than left behind: dead CSS is the kind of thing the next person keeps
   because they cannot prove nothing uses it. Grepped, nothing does. */

.wrap{max-width:820px;margin:0 auto;padding:16px 14px 28px}

.tabs{position:fixed;left:0;right:0;bottom:0;z-index:30;background:var(--paper);
  border-top:1px solid var(--line);display:flex;
  padding-bottom:env(safe-area-inset-bottom)}
.tabs button{flex:1;border:none;background:none;padding:9px 2px 8px;cursor:pointer;
  color:var(--slate-soft);font-size:10.5px;font-weight:700;letter-spacing:.2px;
  display:flex;flex-direction:column;align-items:center;gap:3px}
.tabs button.on{color:var(--rust)}
.tabs .ic{font-size:18px;line-height:1}

/* ── Blocks ──────────────────────────────────────────────────────────────*/
.card{background:var(--paper);border-radius:var(--radius);box-shadow:var(--shadow);
  padding:16px 17px;margin-bottom:13px}
.card h2{font-size:15px;margin-bottom:11px}
.sect{font-size:10.5px;font-weight:800;letter-spacing:1.3px;color:var(--slate-soft);
  text-transform:uppercase;margin:22px 3px 9px}
.sect:first-child{margin-top:4px}

/* ── A section that folds ──────────────────────────────────────────────────
   ★ IT IS A REAL <button>, not a div with a handler, so focus, Enter and the
   pressed state all come free. Same call as the Month tab tiles.
   ⚠️ THE HEADLINE STAYS VISIBLE WHEN IT IS SHUT. A fold that hides everything
   turns a long page into a page of closed doors with no labels, which is worse
   than scrolling: you have to open each one to find out whether you needed it.
   The summary on the right is what makes the shut version worth reading. */
button.sect{display:flex;align-items:center;justify-content:space-between;gap:11px;
  width:100%;background:var(--paper);border:1px solid var(--line);border-radius:var(--radius);
  padding:13px 14px;margin:14px 0 11px;cursor:pointer;font-family:inherit;text-align:left;
  color:var(--ink);font-size:11px;box-shadow:var(--shadow)}
button.sect:first-child{margin-top:4px}

/* ── The colour on a section ───────────────────────────────────────────────
   ★★ TWO COLOUR SYSTEMS ON ONE ROW, AND THEY ANSWER DIFFERENT QUESTIONS.
   The tile on the LEFT says what a section IS, and never changes. The summary
   on the RIGHT says whether it is FINE, and changes with the books. Keeping
   them apart is what stops the page becoming a wall of colour nobody reads:
   the left is furniture, the right is the alarm.

   ⚠️ FIVE GROUPS, AND ALL OF THEM COME OFF THE EXISTING PALETTE. Green is
   money arriving and rust is money leaving, exactly as they mean on every
   other screen in this app. A sixth colour invented for this page would teach
   a meaning that only holds here.

     in    money arriving          green
     out   money leaving           rust
     bank  the account itself      navy
     rec   records and paperwork   sand
     mix   money that is neither   slate
     set   setup and the outside   slate blue

   ⚠️ THE TILE IS DECORATION AND IS HIDDEN FROM SCREEN READERS. The heading
   beside it already says the same thing in words; read aloud, "black square,
   The business" is noise. aria-hidden on the span, no label. */
button.sect .fic{width:30px;height:30px;border-radius:9px;flex-shrink:0;
  display:flex;align-items:center;justify-content:center;font-size:16px;line-height:1;
  font-weight:700;letter-spacing:0}
/* ⚠️ THE ARROWS NEED MORE SIZE THAN THE BLOCKS TO CARRY THE SAME WEIGHT. A
   filled square is solid ink at any size; an arrow is two thin strokes, and at
   the same font-size it reads as a fainter tile rather than a different one.
   Bumped by eye against a real render, not guessed. */
button.sect .fic.f-in,button.sect .fic.f-out,button.sect .fic.f-mix{font-size:19px}
button.sect .fic.f-in{background:var(--good-soft);color:var(--good)}
button.sect .fic.f-out{background:var(--rust-soft);color:var(--rust)}
button.sect .fic.f-bank{background:#E2E8ED;color:var(--navy)}
button.sect .fic.f-rec{background:#F6EEDC;color:#8A6520}
button.sect .fic.f-mix{background:#E7EAEE;color:var(--slate)}
button.sect .fic.f-set{background:#E9EFF4;color:var(--slate)}

/* A shut section is quiet. An open one takes the colour of its own group into
   its border, so it is obvious which one you are inside when the body below it
   runs longer than the screen.
   ⚠️ AN OPEN BAR AND ITS BODY ARE ONE OBJECT. Left as two rounded rectangles
   with a gap between them, the bar reads as a heading that happens to sit
   above an unrelated card. Squaring the corners where they meet and closing
   the gap is what makes the body look like it belongs to the thing you
   tapped. */
button.sect.open{margin-bottom:0;border-bottom-left-radius:0;border-bottom-right-radius:0}
button.sect.open + .card{border-top-left-radius:0;border-top-right-radius:0}
button.sect.open:has(.f-in){border-color:#BCDCC9}
button.sect.open:has(.f-out){border-color:#EFC9BC}
button.sect.open:has(.f-bank){border-color:#C2CDD6}
button.sect.open:has(.f-rec){border-color:#E4D3AC}
button.sect.open:has(.f-mix),button.sect.open:has(.f-set){border-color:var(--steel)}
/* ⚠️ min-width:0 OR A LONG TITLE CLIPS. A flex item will not shrink below
   its content width without it, so the longest heading ran under the summary
   on a phone instead of wrapping. Seen on a 430px screen, not reasoned about. */
button.sect .fname{letter-spacing:1.3px;font-weight:800;text-transform:uppercase;
  min-width:0;flex:1;line-height:1.45}
button.sect .fright{display:flex;align-items:center;gap:9px;flex-shrink:0}
button.sect .fsum{font-size:12px;font-weight:600;letter-spacing:0;text-transform:none;
  color:var(--slate-soft);text-align:right}
button.sect .fsum.warn{color:var(--warn)}
button.sect .fsum.ok{color:var(--good)}
button.sect .chev{color:var(--steel);font-size:11px;width:10px;text-align:center}
/* margin-bottom for an open bar is set once, up with the rule that squares its
   corners, because the two are the same decision: the bar and its body are one
   object. It was set twice and the later 9px quietly won, leaving a gap under
   corners that had already been squared to close it. */
button.sect.open .chev{color:var(--slate-soft)}
/* ★ THE CARD NEXT TO A SHUT HEADING IS HIDDEN, and that is why no section body
   had to be edited to make this work. Every section on the More tab is a
   heading followed by exactly one card, which was checked rather than assumed.
   A section that grows a SECOND card will only hide its first: put the extra
   content inside the same card. */
button.sect:not(.open) + .card{display:none}

.monthbar{display:flex;align-items:center;gap:10px;margin-bottom:13px}
.monthbar .lbl{font-weight:800;font-size:18px;flex:1;text-align:center}
.monthbar button{width:40px;height:40px;border-radius:11px;border:1px solid var(--line);
  background:var(--paper);font-size:17px;cursor:pointer;color:var(--navy);font-weight:700}

/* Month | Year. ⚠️ THE SEGMENTS OVERRIDE .monthbar button's fixed 40px square,
   which is sized for an arrow and would crop a word. They sit inside one
   bordered pill so it reads as a single control with two states rather than as
   two buttons that happen to be touching. Still 38px tall inside a 40px pill:
   that is the finger, and shrinking a control because its label is small is
   how a control ends up hard to hit. */
.monthbar .segs{display:flex;border:1px solid var(--line);border-radius:11px;overflow:hidden;
  background:var(--paper);flex-shrink:0}
.monthbar button.seg{width:auto;height:38px;padding:0 13px;border:0;border-radius:0;
  font-size:13px;font-weight:800;color:var(--slate-soft)}
.monthbar button.seg.on{background:var(--navy);color:#fff}
/* 🐛 "October 2026" WRAPPED TO TWO LINES BELOW 375px and the bar grew to 54px.
   Measured across 320/359/360/375/430/834, not guessed: the wrap zone runs from
   the narrowest phone up to 374px, and 375 fits on one row with room to spare.
   Shrinking the type to make it fit is the wrong trade — this label is the
   answer to "what am I looking at". The segment takes its own full-width row
   instead, which is a deliberate layout rather than a squeeze. */
@media (max-width:374px){
  .monthbar{flex-wrap:wrap}
  .monthbar .segs{flex-basis:100%}
  .monthbar button.seg{flex:1}
}

.tiles{display:grid;grid-template-columns:1fr 1fr;gap:11px;margin-bottom:13px}
/* ⚠️ A TILE IS A BUTTON NOW, so it has to be told not to look like one. A
   <button> brings its own border, font, centred text and background, and every
   one of those has to be reset or six numbers on the Month tab suddenly look
   like six form controls. `font:inherit` and `text-align:left` are the two that
   actually change the look; the rest stop the browser's defaults leaking in. */
.tile{background:var(--paper);border-radius:var(--radius);box-shadow:var(--shadow);padding:14px 15px;
  border:0;font:inherit;color:inherit;text-align:left;width:100%;display:block}
button.tile{cursor:pointer;-webkit-appearance:none;appearance:none}
button.tile:active{transform:translateY(1px)}
.tile .k{font-size:10.5px;font-weight:800;letter-spacing:1.1px;color:var(--slate-soft);
  text-transform:uppercase;margin-bottom:5px}
.tile .v{font-size:23px;font-weight:800;letter-spacing:-.6px}
.tile .n{font-size:12px;color:var(--slate-soft);margin-top:3px}
.tile.wide{grid-column:1 / -1}
.tile.dark{background:var(--navy);color:#F2F4F5}
.tile.dark .k{color:#9FB0BE}
.tile.dark .n{color:#9FB0BE}
.v.good{color:var(--good)}
.v.bad{color:var(--rust)}

.rows{display:flex;flex-direction:column}
.row{display:flex;align-items:center;gap:12px;padding:12px 0;border-bottom:1px solid var(--line);
  text-align:left;background:none;border-left:none;border-right:none;border-top:none;
  width:100%;font:inherit;color:inherit;cursor:pointer}
.row:last-child{border-bottom:none}
.row .main{flex:1;min-width:0}
.row .t{font-weight:700;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.row .s{font-size:12.5px;color:var(--slate-soft);margin-top:2px}
.row .amt{font-weight:800;text-align:right;white-space:nowrap}
.row .amt .s{font-weight:600}

/* Routes he has driven before, above the mileage form. ⚠️ THEY WRAP RATHER
   THAN SCROLL SIDEWAYS. A horizontal strip hides whatever is off the right
   edge, and a preset nobody can see is a preset nobody uses. Four of these is
   two short rows on a phone, which fits without pushing the form off screen.
   44px tall, the accessibility minimum, because this is a thumb target sitting
   directly above the fields it fills. */
.chips{display:flex;flex-wrap:wrap;gap:8px;margin:0 0 14px}
.chip{display:inline-flex;align-items:center;gap:7px;min-height:44px;padding:9px 14px;
  border:1px solid var(--line);border-radius:12px;background:var(--paper);
  font:inherit;font-size:13.5px;font-weight:700;color:var(--navy);cursor:pointer;text-align:left}
.chip .q{font-weight:600;color:var(--slate-soft);white-space:nowrap}
.chip:active{transform:translateY(1px)}

.pill{display:inline-block;padding:2px 9px;border-radius:999px;font-size:11px;font-weight:800;
  letter-spacing:.3px;background:var(--wash);color:var(--slate-soft);white-space:nowrap}
.pill.paid{background:var(--good-soft);color:var(--good)}
.pill.late{background:var(--rust-soft);color:var(--warn)}
.pill.sent{background:#E9EFF4;color:var(--slate)}
.pill.draft{background:#EFEFEF;color:#6B6B6B}
.pill.void{background:#F3E7E7;color:#95312B;text-decoration:line-through}

.empty{color:var(--slate-soft);text-align:center;padding:26px 10px;font-size:14px}

/* ── Forms ───────────────────────────────────────────────────────────────*/
label{display:block;margin-bottom:11px}
label .l{font-size:12px;font-weight:700;color:var(--slate-soft);margin-bottom:5px;display:block}
input,select,textarea{
  width:100%;padding:11px 12px;border:1px solid var(--line);border-radius:10px;
  background:var(--paper);color:var(--ink);
  font-size:16px; /* never lower — see the note at the top of this file */
  font-family:inherit;line-height:1.35}
input:focus,select:focus,textarea:focus{outline:2px solid var(--slate);outline-offset:-1px}
textarea{min-height:74px;resize:vertical}
/* ⚠️ A TWO-ROW TEXTAREA IS A ONE-SENTENCE FIELD, NOT A NOTES BOX. The 74px
   above is right for store notes, which want room; forcing it on the memo,
   description and purpose fields would make every form noticeably taller for
   text that is usually one line. min-height:0 hands the sizing back to the
   rows attribute, so it starts about the height of an input and grows to two
   lines when the text needs it. */
textarea[rows="2"]{min-height:0}
/* ⚠️⚠️ iOS GIVES `input[type=date]` A NATIVE INTRINSIC WIDTH THAT `width:100%`
   DOES NOT BEAT. Reported with a screenshot on 15 Aug 2026, on the "Between you
   and the business" sheet: the Date box grew past its half of the row and sat
   ON TOP of the Amount box beside it, so the amount could not be read or
   tapped. Two boxes overlapping on a money form is not cosmetic.

   ⚠️ CHROMIUM DOES NOT REPRODUCE IT. Measured at iPhone width with this very
   stylesheet: the date input shrank to its column exactly, 190px in a 190px
   label, an 11px gap and no overlap. So the reset below is the cause as well
   as it can be identified from here, and it is NOT the part being relied on.

   ⇒ THREE LAYERS, AND THE LAST ONE CANNOT FAIL:
   1. `appearance:none` drops the native control, which is what carries the
      stubborn intrinsic width. The box is already styled by the rules above,
      so nothing is lost by taking the platform's version off.
   2. `flex-wrap` lets the row break.
   3. The flex basis REPLACES `min-width:0`, and that swap is the actual fix.
      `min-width:0` let the LABEL shrink while the input inside it refused to,
      which is precisely how one box ends up drawn over its neighbour. Sizing
      the label to its content instead means a field that will not shrink
      pushes its partner onto the next line rather than over it. Stacked and
      readable beats side by side and unreadable. */
input[type="date"]{-webkit-appearance:none;appearance:none}
.two{display:flex;flex-wrap:wrap;gap:11px}
.two label{flex:1 1 132px}
.hint{font-size:12px;color:var(--slate-soft);margin:-6px 0 12px}

.btn{padding:12px 18px;border-radius:11px;border:1px solid var(--line);background:var(--paper);
  color:var(--ink);font-weight:700;font-size:15px;cursor:pointer}
.btn.go{background:var(--navy);border-color:var(--navy);color:#fff}
.btn.rust{background:var(--rust);border-color:var(--rust);color:#fff}
.btn.danger{color:var(--rust);border-color:#EBC7BC}
.btn:disabled{opacity:.5;cursor:default}
.btn.full{width:100%}
.btnrow{display:flex;gap:10px;flex-wrap:wrap;margin-top:4px}
.btnrow .btn{flex:1;min-width:130px}

.note{padding:11px 13px;border-radius:10px;font-size:13.5px;margin-bottom:12px}
.note.warn{background:var(--rust-soft);color:var(--warn)}
.note.ok{background:var(--good-soft);color:var(--good)}
.note.info{background:#E9EFF4;color:var(--slate)}
/* ★ THE ONLY RED IN THE APP, AND THE ONLY PLACE THIS CLASS IS USED.
   `.warn` above is the same rust the app already spends on late invoices, so a
   second orange box would read as more of the same. This has to be visibly a
   step past it: deeper fill, darker text, and a solid bar down the side that
   nothing else here has. Used once, on the Month tab, for a personal purchase
   paid out of the business account. Keep it that way — the moment a second
   thing is red, neither of them is urgent any more. */
.note.red{background:#FBDCD5;color:#8E2C16;border-left:4px solid #C0341A}

/* ── Sheet ───────────────────────────────────────────────────────────────*/
.scrim{position:fixed;inset:0;background:rgba(20,28,36,.5);z-index:40;
  display:flex;align-items:flex-end;justify-content:center}
/* 🐛 THE TOP OF A FULL-HEIGHT SHEET RAN UNDER THE iPHONE CLOCK.
   The sheet is pinned to the BOTTOM and capped by its height, so the cap is
   what decides where its top edge lands. At a flat 92vh that edge sat about
   70px down, which in a standalone PWA is inside the status bar: no browser
   chrome is there to push the page down, so the clock and the battery are
   painted straight over the page. The first line of a long form collided with
   them, which is exactly what a screenshot from a real iPad showed.
   ⚠️ THE BOTTOM INSET WAS ALREADY HANDLED AND THE TOP ONE WAS NOT. Taking the
   top inset off the cap moves the top edge down by the height of the status
   bar and nothing else changes. Off a phone the inset is 0px, so this is
   92vh exactly as before.
   ⚠️ THE SAME TRAP AS THE DEMO CHIPS (Aug 8 2026). Anything pinned near the
   top or bottom edge of this app needs its safe-area inset, and it will look
   perfect in a desktop browser either way. */
.sheet{background:var(--paper);width:100%;max-width:560px;overflow-y:auto;
  max-height:calc(92vh - env(safe-area-inset-top));
  border-radius:18px 18px 0 0;padding:20px 18px calc(26px + env(safe-area-inset-bottom))}
.sheet h2{font-size:17px;margin-bottom:14px}
.sheet .x{float:right;border:none;background:none;font-size:22px;color:var(--slate-soft);
  cursor:pointer;line-height:1;padding:0 2px}
@media (min-width:620px){
  .scrim{align-items:center}
  .sheet{border-radius:18px;max-height:86vh}
}

.fab{position:fixed;right:16px;bottom:calc(var(--tabbar) + 16px + env(safe-area-inset-bottom));
  z-index:25;width:54px;height:54px;border-radius:50%;border:none;background:var(--rust);
  color:#fff;font-size:27px;line-height:1;cursor:pointer;box-shadow:0 4px 14px rgba(194,78,50,.4)}

.kv{display:flex;justify-content:space-between;gap:14px;padding:6px 0;font-size:14px}
.kv span:first-child{color:var(--slate-soft)}
.kv span:last-child{font-weight:700;text-align:right}
.kv.big span:last-child{font-size:17px}

@media (min-width:620px){
  .tiles{grid-template-columns:repeat(3,1fr)}
  .tile.wide{grid-column:span 3}
}
