Express + SQLite (node:sqlite, no native build step) family calendar: parent accounts with household invites, per-child calendars with save/duplicate/print, a token-gated read-only kiosk view for tablets, and polling to keep parent and kiosk views in sync. Defaults to port 3007.
452 lines
9.7 KiB
CSS
452 lines
9.7 KiB
CSS
:root{
|
|
--bg: #F1F5FB;
|
|
--card: #FFFFFF;
|
|
--ink: #2E3446;
|
|
--ink-soft: #6B7280;
|
|
--line: #E3E8F0;
|
|
|
|
--morning: #FF8C64;
|
|
--morning-bg: #FFF0E7;
|
|
--school: #4A90D9;
|
|
--school-bg: #E9F2FC;
|
|
--after: #4FAE72;
|
|
--after-bg: #E9F7EE;
|
|
--evening: #8B7FD1;
|
|
--evening-bg: #F0EDFB;
|
|
|
|
--today-ring: #FFC94A;
|
|
--danger: #D14343;
|
|
}
|
|
|
|
*{ box-sizing: border-box; }
|
|
|
|
body{
|
|
margin:0;
|
|
background: var(--bg);
|
|
font-family: 'Nunito', sans-serif;
|
|
color: var(--ink);
|
|
padding: 24px 16px 60px;
|
|
}
|
|
|
|
a{ color: var(--school); }
|
|
|
|
h1{
|
|
font-family: 'Baloo 2', sans-serif;
|
|
font-size: 2rem;
|
|
margin: 0;
|
|
color: var(--ink);
|
|
}
|
|
h1 span{ color: var(--morning); }
|
|
|
|
header{
|
|
max-width: 1400px;
|
|
margin: 0 auto 20px;
|
|
display:flex;
|
|
align-items:center;
|
|
justify-content: space-between;
|
|
flex-wrap: wrap;
|
|
gap: 12px;
|
|
}
|
|
|
|
.subtitle{
|
|
font-size: 0.95rem;
|
|
color: var(--ink-soft);
|
|
margin-top: 2px;
|
|
}
|
|
|
|
.toolbar{
|
|
display:flex;
|
|
gap: 10px;
|
|
flex-wrap: wrap;
|
|
}
|
|
|
|
button.tool, a.tool{
|
|
font-family: 'Nunito', sans-serif;
|
|
font-weight: 800;
|
|
font-size: 0.85rem;
|
|
border: none;
|
|
border-radius: 999px;
|
|
padding: 10px 18px;
|
|
cursor: pointer;
|
|
background: var(--card);
|
|
color: var(--ink);
|
|
border: 2px solid var(--line);
|
|
transition: transform .12s ease, background .12s ease;
|
|
text-decoration: none;
|
|
display: inline-block;
|
|
}
|
|
button.tool:hover, a.tool:hover{ transform: translateY(-1px); background: #F7F9FC; }
|
|
button.tool.primary, a.tool.primary{ background: var(--school); color: white; border-color: var(--school); }
|
|
button.tool.primary:hover, a.tool.primary:hover{ background: #3d7fc4; }
|
|
button.tool.danger{ background: var(--card); color: var(--danger); border-color: #F3D0D0; }
|
|
button.tool.danger:hover{ background: #FDF1F1; }
|
|
button.tool:disabled{ opacity: .5; cursor: default; transform:none; }
|
|
|
|
.board{
|
|
max-width: 1400px;
|
|
margin: 0 auto;
|
|
display: grid;
|
|
grid-template-columns: repeat(5, 1fr);
|
|
gap: 14px;
|
|
}
|
|
|
|
.weekend-toggle-wrap{
|
|
max-width: 1400px;
|
|
margin: 14px auto 0;
|
|
display: grid;
|
|
grid-template-columns: repeat(2, 1fr);
|
|
gap: 14px;
|
|
}
|
|
|
|
.day-card{
|
|
background: var(--card);
|
|
border-radius: 20px;
|
|
padding: 14px;
|
|
display:flex;
|
|
flex-direction:column;
|
|
gap: 10px;
|
|
border: 3px solid transparent;
|
|
box-shadow: 0 2px 10px rgba(46,52,70,0.06);
|
|
}
|
|
|
|
.day-card.today{
|
|
border-color: var(--today-ring);
|
|
box-shadow: 0 4px 18px rgba(255,201,74,0.35);
|
|
}
|
|
|
|
.day-head{
|
|
display:flex;
|
|
align-items:baseline;
|
|
justify-content: space-between;
|
|
}
|
|
|
|
.day-name{
|
|
font-family: 'Baloo 2', sans-serif;
|
|
font-weight: 700;
|
|
font-size: 1.15rem;
|
|
}
|
|
|
|
.today-badge{
|
|
font-size: 0.65rem;
|
|
font-weight: 800;
|
|
background: var(--today-ring);
|
|
color: #6B4A00;
|
|
padding: 3px 9px;
|
|
border-radius: 999px;
|
|
letter-spacing: .03em;
|
|
}
|
|
|
|
.block{
|
|
border-radius: 14px;
|
|
padding: 10px 10px 8px;
|
|
}
|
|
|
|
.block.morning{ background: var(--morning-bg); }
|
|
.block.school{ background: var(--school-bg); }
|
|
.block.after{ background: var(--after-bg); }
|
|
.block.evening{ background: var(--evening-bg); }
|
|
|
|
.block-title{
|
|
font-family: 'Baloo 2', sans-serif;
|
|
font-weight: 700;
|
|
font-size: 0.85rem;
|
|
display:flex;
|
|
align-items:center;
|
|
gap: 6px;
|
|
margin-bottom: 6px;
|
|
}
|
|
.morning .block-title{ color: #C0501F; }
|
|
.school .block-title{ color: #2C6BAF; }
|
|
.after .block-title{ color: #2D7B4C; }
|
|
.evening .block-title{ color: #5F51B0; }
|
|
|
|
.task{
|
|
display:flex;
|
|
align-items:flex-start;
|
|
gap: 8px;
|
|
padding: 5px 4px;
|
|
border-radius: 8px;
|
|
}
|
|
.task:hover{ background: rgba(255,255,255,0.6); }
|
|
.task:hover .del{ opacity: 1; }
|
|
|
|
.task input[type=checkbox]{
|
|
margin-top: 3px;
|
|
width: 18px;
|
|
height: 18px;
|
|
flex: none;
|
|
accent-color: var(--ink);
|
|
cursor: pointer;
|
|
}
|
|
.task.kiosk input[type=checkbox]{
|
|
width: 24px;
|
|
height: 24px;
|
|
}
|
|
|
|
.task-text{
|
|
flex: 1;
|
|
font-size: 0.92rem;
|
|
font-weight: 700;
|
|
outline: none;
|
|
line-height: 1.25;
|
|
padding: 1px 2px;
|
|
border-radius: 4px;
|
|
}
|
|
.task-text:focus{ background: rgba(255,255,255,0.85); }
|
|
.task.done .task-text{
|
|
text-decoration: line-through;
|
|
opacity: 0.45;
|
|
}
|
|
|
|
.del{
|
|
opacity: 0;
|
|
border: none;
|
|
background: none;
|
|
color: var(--ink-soft);
|
|
font-weight: 800;
|
|
cursor: pointer;
|
|
font-size: 0.85rem;
|
|
padding: 0 3px;
|
|
transition: opacity .12s ease;
|
|
}
|
|
.del:hover{ color: var(--danger); }
|
|
|
|
.add-task{
|
|
background: none;
|
|
border: none;
|
|
color: var(--ink-soft);
|
|
font-size: 0.82rem;
|
|
font-weight: 800;
|
|
cursor: pointer;
|
|
padding: 4px 4px 2px;
|
|
opacity: 0.75;
|
|
}
|
|
.add-task:hover{ opacity: 1; text-decoration: underline; }
|
|
|
|
.legend{
|
|
max-width: 1400px;
|
|
margin: 22px auto 0;
|
|
display:flex;
|
|
gap: 16px;
|
|
flex-wrap: wrap;
|
|
font-size: 0.82rem;
|
|
color: var(--ink-soft);
|
|
align-items:center;
|
|
}
|
|
.legend .dot{
|
|
display:inline-block;
|
|
width: 10px; height:10px;
|
|
border-radius: 50%;
|
|
margin-right: 5px;
|
|
}
|
|
.legend .item{ display:flex; align-items:center; }
|
|
|
|
.hint{
|
|
max-width: 1400px;
|
|
margin: 6px auto 0;
|
|
font-size: 0.78rem;
|
|
color: var(--ink-soft);
|
|
}
|
|
|
|
@media (max-width: 1100px){
|
|
.board{ grid-template-columns: repeat(2, 1fr); }
|
|
.weekend-toggle-wrap{ grid-template-columns: 1fr; }
|
|
}
|
|
@media (max-width: 600px){
|
|
.board{ grid-template-columns: 1fr; }
|
|
}
|
|
|
|
@media print{
|
|
body{ background: white; padding: 0; }
|
|
.toolbar, .add-task, .del, .hint, .period-toggles, nav.crumbs{ display:none !important; }
|
|
.board{ grid-template-columns: repeat(5, 1fr); gap: 8px; }
|
|
.day-card{ box-shadow:none; border: 2px solid var(--line) !important; break-inside: avoid; }
|
|
.weekend-toggle-wrap{ margin-top: 8px; grid-template-columns: repeat(2,1fr); }
|
|
}
|
|
|
|
#weekendWrap.hidden{ display:none; }
|
|
|
|
body.hide-morning .block.morning{ display:none; }
|
|
body.hide-school .block.school{ display:none; }
|
|
body.hide-after .block.after{ display:none; }
|
|
body.hide-evening .block.evening{ display:none; }
|
|
|
|
[contenteditable="true"]{
|
|
outline: none;
|
|
border-radius: 4px;
|
|
padding: 0 2px;
|
|
}
|
|
[contenteditable="true"]:focus{ background: rgba(255,255,255,0.7); }
|
|
|
|
.period-toggles{
|
|
max-width: 1400px;
|
|
margin: 0 auto 18px;
|
|
display:flex;
|
|
gap: 18px;
|
|
flex-wrap: wrap;
|
|
align-items:center;
|
|
background: var(--card);
|
|
border: 2px solid var(--line);
|
|
border-radius: 14px;
|
|
padding: 10px 16px;
|
|
}
|
|
.period-toggles .label{
|
|
font-size: 0.8rem;
|
|
font-weight: 800;
|
|
color: var(--ink-soft);
|
|
}
|
|
.period-toggles label.opt{
|
|
display:flex;
|
|
align-items:center;
|
|
gap: 6px;
|
|
font-size: 0.85rem;
|
|
font-weight: 700;
|
|
cursor: pointer;
|
|
}
|
|
.period-toggles input[type=checkbox]{
|
|
width: 16px; height:16px;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.block-title .icon{ margin-right: 2px; }
|
|
.block-title .label{
|
|
outline: none;
|
|
border-radius: 4px;
|
|
padding: 0 2px;
|
|
}
|
|
.block-title .label:focus{ background: rgba(255,255,255,0.75); }
|
|
|
|
/* --- App chrome shared across auth/dashboard pages --- */
|
|
|
|
nav.crumbs{
|
|
max-width: 1400px;
|
|
margin: 0 auto 14px;
|
|
font-size: 0.85rem;
|
|
color: var(--ink-soft);
|
|
}
|
|
nav.crumbs a{ text-decoration: none; font-weight: 700; }
|
|
|
|
.auth-wrap{
|
|
max-width: 420px;
|
|
margin: 60px auto;
|
|
background: var(--card);
|
|
border-radius: 20px;
|
|
padding: 32px;
|
|
box-shadow: 0 2px 10px rgba(46,52,70,0.06);
|
|
}
|
|
.auth-wrap h1{ font-size: 1.5rem; margin-bottom: 4px; }
|
|
.auth-wrap p.lead{ color: var(--ink-soft); margin-top: 0; margin-bottom: 20px; font-size: 0.9rem; }
|
|
|
|
.field{ margin-bottom: 14px; display:flex; flex-direction:column; gap: 6px; }
|
|
.field label{ font-size: 0.82rem; font-weight: 800; color: var(--ink-soft); }
|
|
.field input{
|
|
font-family: 'Nunito', sans-serif;
|
|
font-size: 0.95rem;
|
|
padding: 10px 12px;
|
|
border-radius: 10px;
|
|
border: 2px solid var(--line);
|
|
outline: none;
|
|
}
|
|
.field input:focus{ border-color: var(--school); }
|
|
|
|
.error-msg{
|
|
background: #FDF1F1;
|
|
border: 2px solid #F3D0D0;
|
|
color: var(--danger);
|
|
border-radius: 10px;
|
|
padding: 10px 12px;
|
|
font-size: 0.85rem;
|
|
font-weight: 700;
|
|
margin-bottom: 14px;
|
|
}
|
|
|
|
.form-actions{ margin-top: 18px; display:flex; flex-direction:column; gap: 10px; }
|
|
.form-actions button.tool{ width: 100%; text-align:center; }
|
|
.switch-link{ font-size: 0.85rem; color: var(--ink-soft); text-align:center; }
|
|
|
|
.section{
|
|
max-width: 1400px;
|
|
margin: 0 auto 28px;
|
|
}
|
|
.section h2{
|
|
font-family: 'Baloo 2', sans-serif;
|
|
font-size: 1.3rem;
|
|
margin: 0 0 12px;
|
|
}
|
|
|
|
.card-grid{
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
|
|
gap: 14px;
|
|
}
|
|
|
|
.entity-card{
|
|
background: var(--card);
|
|
border-radius: 16px;
|
|
padding: 16px;
|
|
border: 2px solid var(--line);
|
|
display:flex;
|
|
flex-direction: column;
|
|
gap: 10px;
|
|
}
|
|
.entity-card h3{ margin: 0; font-family: 'Baloo 2', sans-serif; font-size: 1.1rem; }
|
|
.entity-card .meta{ font-size: 0.8rem; color: var(--ink-soft); }
|
|
.entity-card .row{ display:flex; gap: 8px; flex-wrap: wrap; }
|
|
.entity-card .row button.tool, .entity-card .row a.tool{ padding: 7px 12px; font-size: 0.78rem; }
|
|
|
|
.empty-state{
|
|
color: var(--ink-soft);
|
|
font-size: 0.9rem;
|
|
padding: 20px;
|
|
text-align: center;
|
|
background: var(--card);
|
|
border: 2px dashed var(--line);
|
|
border-radius: 16px;
|
|
}
|
|
|
|
.kiosk-lock-note{
|
|
max-width: 1400px;
|
|
margin: 0 auto 14px;
|
|
font-size: 0.85rem;
|
|
color: var(--ink-soft);
|
|
display:flex;
|
|
align-items:center;
|
|
gap: 8px;
|
|
}
|
|
|
|
.modal-backdrop{
|
|
position: fixed; inset: 0;
|
|
background: rgba(46,52,70,0.35);
|
|
display:flex; align-items:center; justify-content:center;
|
|
padding: 20px;
|
|
z-index: 50;
|
|
}
|
|
.modal-backdrop.hidden{ display:none; }
|
|
.modal{
|
|
background: var(--card);
|
|
border-radius: 20px;
|
|
padding: 24px;
|
|
max-width: 420px;
|
|
width: 100%;
|
|
}
|
|
.modal h2{ margin-top:0; font-family:'Baloo 2', sans-serif; }
|
|
.modal .form-actions{ flex-direction: row; }
|
|
.modal .form-actions button{ flex: 1; }
|
|
|
|
.toast{
|
|
position: fixed;
|
|
bottom: 20px; left: 50%;
|
|
transform: translateX(-50%);
|
|
background: var(--ink);
|
|
color: white;
|
|
padding: 10px 18px;
|
|
border-radius: 999px;
|
|
font-size: 0.85rem;
|
|
font-weight: 700;
|
|
opacity: 0;
|
|
pointer-events: none;
|
|
transition: opacity .2s ease;
|
|
z-index: 100;
|
|
}
|
|
.toast.show{ opacity: 1; }
|