@ -0,0 +1,53 @@ |
|||||
|
.. image:: https://img.shields.io/badge/license-AGPL--3-blue.svg |
||||
|
:target: https://www.gnu.org/licenses/agpl-3.0-standalone.html |
||||
|
:alt: License: AGPL-3 |
||||
|
|
||||
|
Systray World Clock |
||||
|
=================== |
||||
|
Module enables user to add world clocks of selected timezones in |
||||
|
the systray dropdown. |
||||
|
|
||||
|
Configuration |
||||
|
============= |
||||
|
The desired timezone and title for the clocks can be configured in |
||||
|
the settings page. |
||||
|
|
||||
|
Company |
||||
|
------- |
||||
|
* `Cybrosys Techno Solutions <https://cybrosys.com/>`__ |
||||
|
|
||||
|
License |
||||
|
------- |
||||
|
GNU AFFERO GENERAL PUBLIC LICENSE, Version 3 (AGPLv3) |
||||
|
(http://www.gnu.org/licenses/agpl-3.0-standalone.html) |
||||
|
|
||||
|
Credits |
||||
|
------- |
||||
|
* Developer: (V18) Mufeeda Shirin, Nivedhya T, |
||||
|
(V17)Busthana Shirin, |
||||
|
(V15) Abhijith PG, |
||||
|
Contact: odoo@cybrosys.com |
||||
|
|
||||
|
Contacts |
||||
|
-------- |
||||
|
* Mail Contact : odoo@cybrosys.com |
||||
|
* Website : https://cybrosys.com |
||||
|
|
||||
|
Bug Tracker |
||||
|
----------- |
||||
|
Bugs are tracked on GitHub Issues. In case of trouble, please check there if |
||||
|
your issue has already been reported. |
||||
|
|
||||
|
Maintainer |
||||
|
========== |
||||
|
.. image:: https://cybrosys.com/images/logo.png |
||||
|
:target: https://cybrosys.com |
||||
|
|
||||
|
This module is maintained by Cybrosys Technologies. |
||||
|
|
||||
|
For support and more information, please visit |
||||
|
`Our Website <https://cybrosys.com/>`__ |
||||
|
|
||||
|
Further information |
||||
|
=================== |
||||
|
HTML Description: `<static/description/index.html>`__ |
@ -0,0 +1,22 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
############################################################################# |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 2025-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
||||
|
# Author: Cybrosys Techno Solutions (odoo@cybrosys.com) |
||||
|
# |
||||
|
# You can modify it under the terms of the GNU AFFERO |
||||
|
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. |
||||
|
# |
||||
|
# This program is distributed in the hope that it will be useful, |
||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
|
# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. |
||||
|
# |
||||
|
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
|
# (AGPL v3) along with this program. |
||||
|
# If not, see <http://www.gnu.org/licenses/>. |
||||
|
# |
||||
|
############################################################################# |
||||
|
from . import models |
@ -0,0 +1,52 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
############################################################################# |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 2025-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
||||
|
# Author: Cybrosys Techno Solutions (odoo@cybrosys.com) |
||||
|
# |
||||
|
# You can modify it under the terms of the GNU AFFERO |
||||
|
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. |
||||
|
# |
||||
|
# This program is distributed in the hope that it will be useful, |
||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
|
# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. |
||||
|
# |
||||
|
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
|
# (AGPL v3) along with this program. |
||||
|
# If not, see <http://www.gnu.org/licenses/>. |
||||
|
# |
||||
|
############################################################################# |
||||
|
{ |
||||
|
'name': "Systray World Clock", |
||||
|
'version': '18.0.1.0.0', |
||||
|
'category': 'Productivity', |
||||
|
'summary': """Keep track of the time in different countries around the |
||||
|
world.""", |
||||
|
'description': """This module adds a world clock in the systray which |
||||
|
displays the time in different countries around the world. |
||||
|
The time zone can be customized in the settings""", |
||||
|
'author': "Cybrosys Techno Solutions", |
||||
|
'company': 'Cybrosys Techno Solutions', |
||||
|
'maintainer': 'Cybrosys Techno Solutions', |
||||
|
'website': "https://www.cybrosys.com", |
||||
|
'depends': ['base', 'web'], |
||||
|
'data': [ |
||||
|
'security/ir.model.access.csv', |
||||
|
'views/systray_world_clock_config_views.xml', |
||||
|
], |
||||
|
'assets': { |
||||
|
'web.assets_backend': [ |
||||
|
'systray_world_clock/static/src/js/SystrayWorldClock.js', |
||||
|
'systray_world_clock/static/src/xml/systray_world_clock.xml', |
||||
|
'systray_world_clock/static/src/scss/systray_world_clock.scss' |
||||
|
], |
||||
|
}, |
||||
|
'images': ['static/description/banner.png'], |
||||
|
'license': 'AGPL-3', |
||||
|
'installable': True, |
||||
|
'auto_install': False, |
||||
|
'application': False, |
||||
|
} |
@ -0,0 +1,6 @@ |
|||||
|
## Module <systray_world_clock> |
||||
|
|
||||
|
#### 15.07.2025 |
||||
|
#### Version 18.0.1.0.0 |
||||
|
##### ADD |
||||
|
- Initial commit for Systray World Clock |
@ -0,0 +1,22 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
############################################################################# |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 2025-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
||||
|
# Author: Cybrosys Techno Solutions (odoo@cybrosys.com) |
||||
|
# |
||||
|
# You can modify it under the terms of the GNU AFFERO |
||||
|
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. |
||||
|
# |
||||
|
# This program is distributed in the hope that it will be useful, |
||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
|
# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. |
||||
|
# |
||||
|
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
|
# (AGPL v3) along with this program. |
||||
|
# If not, see <http://www.gnu.org/licenses/>. |
||||
|
# |
||||
|
############################################################################# |
||||
|
from . import systray_world_clock_config |
@ -0,0 +1,52 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
############################################################################# |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 2025-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
||||
|
# Author: Cybrosys Techno Solutions (odoo@cybrosys.com) |
||||
|
# |
||||
|
# You can modify it under the terms of the GNU AFFERO |
||||
|
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. |
||||
|
# |
||||
|
# This program is distributed in the hope that it will be useful, |
||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
|
# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. |
||||
|
# |
||||
|
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
|
# (AGPL v3) along with this program. |
||||
|
# If not, see <http://www.gnu.org/licenses/>. |
||||
|
# |
||||
|
############################################################################# |
||||
|
import pytz |
||||
|
from datetime import datetime |
||||
|
from odoo import api, fields, models |
||||
|
from odoo.addons.base.models.res_partner import _tz_get |
||||
|
|
||||
|
|
||||
|
class SystrayWorldClockConfig(models.Model): |
||||
|
"""A model representing the configuration of a world clock in the systray. |
||||
|
""" |
||||
|
_name = 'systray.world.clock.config' |
||||
|
_description = 'Systray World Clock Configuration' |
||||
|
|
||||
|
name = fields.Char(string='Location', required=True, |
||||
|
help='Location associated with this clock.') |
||||
|
tz = fields.Selection(_tz_get, required=True, string='Timezone', |
||||
|
help='Timezone of the clock.') |
||||
|
offset = fields.Float(string="Offset", |
||||
|
help='The time difference between the timezone and ' |
||||
|
'UTC, in hours.') |
||||
|
|
||||
|
@api.onchange('tz') |
||||
|
def _onchange_tz(self): |
||||
|
"""Calculate the time offset between the selected timezone and UTC. |
||||
|
This method is called automatically whenever the timezone field is |
||||
|
changed. |
||||
|
""" |
||||
|
if self.tz: |
||||
|
utc_dt = pytz.utc.localize(datetime.utcnow()) |
||||
|
tz = pytz.timezone(self.tz) |
||||
|
local_dt = utc_dt.astimezone(tz) |
||||
|
self.offset = local_dt.utcoffset().total_seconds() / 3600 |
|
After Width: | Height: | Size: 2.2 KiB |
After Width: | Height: | Size: 28 KiB |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 210 KiB |
After Width: | Height: | Size: 209 KiB |
After Width: | Height: | Size: 109 KiB |
After Width: | Height: | Size: 495 B |
After Width: | Height: | Size: 1.0 KiB |
After Width: | Height: | Size: 624 B |
After Width: | Height: | Size: 136 KiB |
After Width: | Height: | Size: 214 KiB |
After Width: | Height: | Size: 36 KiB |
After Width: | Height: | Size: 3.6 KiB |
After Width: | Height: | Size: 310 B |
After Width: | Height: | Size: 929 B |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 3.3 KiB |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 17 KiB |
After Width: | Height: | Size: 542 B |
After Width: | Height: | Size: 576 B |
After Width: | Height: | Size: 733 B |
After Width: | Height: | Size: 4.3 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 4.0 KiB |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 150 KiB |
After Width: | Height: | Size: 2.2 KiB |
After Width: | Height: | Size: 911 B |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 600 B |
After Width: | Height: | Size: 673 B |
After Width: | Height: | Size: 2.0 KiB |
After Width: | Height: | Size: 462 B |
After Width: | Height: | Size: 2.1 KiB |
After Width: | Height: | Size: 926 B |
After Width: | Height: | Size: 9.0 KiB |
After Width: | Height: | Size: 23 KiB |
After Width: | Height: | Size: 7.0 KiB |
After Width: | Height: | Size: 878 B |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 653 B |
After Width: | Height: | Size: 800 B |
After Width: | Height: | Size: 905 B |
After Width: | Height: | Size: 189 KiB |
After Width: | Height: | Size: 4.3 KiB |
After Width: | Height: | Size: 839 B |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 5.9 KiB |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 34 KiB |
After Width: | Height: | Size: 26 KiB |
After Width: | Height: | Size: 3.8 KiB |
After Width: | Height: | Size: 23 KiB |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 2.3 KiB |
After Width: | Height: | Size: 427 B |
After Width: | Height: | Size: 627 B |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 988 B |
After Width: | Height: | Size: 3.7 KiB |
After Width: | Height: | Size: 5.0 KiB |
After Width: | Height: | Size: 875 B |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 790 KiB |
After Width: | Height: | Size: 89 KiB |
After Width: | Height: | Size: 746 KiB |
After Width: | Height: | Size: 716 KiB |
After Width: | Height: | Size: 742 KiB |
After Width: | Height: | Size: 87 KiB |
After Width: | Height: | Size: 448 KiB |
After Width: | Height: | Size: 454 KiB |
After Width: | Height: | Size: 35 KiB |
After Width: | Height: | Size: 485 KiB |
After Width: | Height: | Size: 503 KiB |
After Width: | Height: | Size: 91 KiB |
After Width: | Height: | Size: 14 KiB |
After Width: | Height: | Size: 33 KiB |
After Width: | Height: | Size: 50 KiB |
After Width: | Height: | Size: 2.3 KiB |
After Width: | Height: | Size: 2.9 KiB |
After Width: | Height: | Size: 2.3 KiB |
After Width: | Height: | Size: 2.7 KiB |
After Width: | Height: | Size: 2.4 KiB |
After Width: | Height: | Size: 2.4 KiB |
After Width: | Height: | Size: 5.2 KiB |
After Width: | Height: | Size: 1.4 KiB |
@ -0,0 +1,136 @@ |
|||||
|
/** @odoo-module **/ |
||||
|
import { Component, useState, onMounted,useRef } from "@odoo/owl"; |
||||
|
import { useService } from "@web/core/utils/hooks"; |
||||
|
import { Dropdown } from "@web/core/dropdown/dropdown"; |
||||
|
import { registry } from "@web/core/registry"; |
||||
|
|
||||
|
export class Analogue extends Component { |
||||
|
static template = "systray_world_clock.AnalogueInterface"; |
||||
|
|
||||
|
setup() { |
||||
|
super.setup(); |
||||
|
this.hoursHandRef = useRef("hoursHand"); |
||||
|
this.minutesHandRef = useRef("minutesHand"); |
||||
|
this.secondsHandRef = useRef("secondsHand"); |
||||
|
this.clockElementRef = useRef("clockElement"); |
||||
|
onMounted(() => { |
||||
|
this.renderClock(); |
||||
|
this.interval = setInterval(() => { |
||||
|
this.renderClock(); |
||||
|
}, 1000); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
calcTime(offset) { |
||||
|
const d = new Date(); |
||||
|
const utc = d.getTime() + (d.getTimezoneOffset() * 60000); |
||||
|
const nd = new Date(utc + (3600000 * offset)); |
||||
|
const options = { |
||||
|
year: 'numeric', |
||||
|
month: 'numeric', |
||||
|
day: 'numeric', |
||||
|
hour: 'numeric', |
||||
|
minute: 'numeric', |
||||
|
hour12: true |
||||
|
}; |
||||
|
return [nd, nd.toLocaleString('en-US', options)]; |
||||
|
} |
||||
|
|
||||
|
renderClock() { |
||||
|
const [nd, localestring] = this.calcTime(this.props.offset); |
||||
|
const h = ((nd.getHours() % 12) + nd.getMinutes() / 59) * 30; |
||||
|
const m = nd.getMinutes() * 6; |
||||
|
const s = nd.getSeconds() * 6; |
||||
|
|
||||
|
// Accessing the refs safely
|
||||
|
if (this.hoursHandRef.el) this.hoursHandRef.el.style.transform = `rotate(${h}deg)`; |
||||
|
if (this.minutesHandRef.el) this.minutesHandRef.el.style.transform = `rotate(${m}deg)`; |
||||
|
if (this.secondsHandRef.el) this.secondsHandRef.el.style.transform = `rotate(${s}deg)`; |
||||
|
|
||||
|
const clockElement = this.clockElementRef.el; |
||||
|
if (clockElement) { |
||||
|
if (18 <= nd.getHours() || nd.getHours() < 6) { |
||||
|
clockElement.classList.add('night-clock'); |
||||
|
} else { |
||||
|
clockElement.classList.remove('night-clock'); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
willUnmount() { |
||||
|
clearInterval(this.interval); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
export class WorldClock extends Component { |
||||
|
static components = { Dropdown, Analogue }; |
||||
|
static template = "systray_world_clock.Systray_clock"; |
||||
|
|
||||
|
setup() { |
||||
|
super.setup(); |
||||
|
this.orm = useService("orm"); |
||||
|
this.action = useService("action"); |
||||
|
this.state = useState({ |
||||
|
isOpen: false, |
||||
|
notes: [], |
||||
|
}); |
||||
|
|
||||
|
this.loadClocks(); |
||||
|
} |
||||
|
|
||||
|
async loadClocks() { |
||||
|
const fields = ['name', 'tz', 'offset']; |
||||
|
const result = await this.orm.call("systray.world.clock.config", "search_read", [], { fields }); |
||||
|
|
||||
|
if (result.length > 0) { |
||||
|
this.state.isOpen = true; |
||||
|
const data = result.map(clock => { |
||||
|
const offsetStr = clock.offset.toString().replace('.', '_'); |
||||
|
const currentClockClass = 'clock' + offsetStr + clock.id; |
||||
|
const [nd, localestring] = this.calcTime(clock.offset); |
||||
|
return { |
||||
|
id: clock.id, |
||||
|
name: clock.name, |
||||
|
offset: clock.offset, |
||||
|
tz: clock.tz, |
||||
|
currentClockClass, |
||||
|
nd, |
||||
|
localestring, |
||||
|
}; |
||||
|
}); |
||||
|
this.state.notes = data; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
calcTime(offset) { |
||||
|
const d = new Date(); |
||||
|
const utc = d.getTime() + (d.getTimezoneOffset() * 60000); |
||||
|
const nd = new Date(utc + (3600000 * offset)); |
||||
|
const options = { |
||||
|
year: 'numeric', |
||||
|
month: 'numeric', |
||||
|
day: 'numeric', |
||||
|
hour: 'numeric', |
||||
|
minute: 'numeric', |
||||
|
hour12: true, |
||||
|
}; |
||||
|
return [nd, nd.toLocaleString('en-US', options)]; |
||||
|
} |
||||
|
|
||||
|
onClickSettings(ev) { |
||||
|
ev.stopPropagation(); |
||||
|
this.action.doAction({ |
||||
|
type: 'ir.actions.act_window', |
||||
|
name: 'Clock Settings', |
||||
|
res_model: 'systray.world.clock.config', |
||||
|
view_mode: 'list,form', |
||||
|
target: 'current', |
||||
|
views: [[false, 'list'], [false, 'form']], |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
export const systrayItem = { |
||||
|
Component: WorldClock, |
||||
|
}; |
||||
|
registry.category("systray").add("WorldClock", systrayItem, { sequence: 0 }); |
@ -0,0 +1,143 @@ |
|||||
|
.systray_clock_dropdown { |
||||
|
padding: 2em; |
||||
|
width: 1100px; |
||||
|
} |
||||
|
.settings_tz { |
||||
|
position: relative; |
||||
|
top: -0.5rem; |
||||
|
color: blueviolet; |
||||
|
background: lavender; |
||||
|
border: aliceblue; |
||||
|
float:right; |
||||
|
} |
||||
|
|
||||
|
#clocks_container { |
||||
|
display: flex; |
||||
|
justify-content: space-evenly; |
||||
|
flex-wrap: wrap; |
||||
|
.time-info { |
||||
|
padding: 10px 30px; |
||||
|
margin: 2em 0; |
||||
|
min-height: 50px; |
||||
|
border: 1px solid #dddddd; |
||||
|
border-radius: 10px; |
||||
|
background-color: transparent; |
||||
|
} |
||||
|
} |
||||
|
.clocks_container:not(:last-child) { |
||||
|
padding: 10px; |
||||
|
min-height: 50px; |
||||
|
border-bottom: 1px solid #9DA1AA; |
||||
|
background-color: transparent; |
||||
|
} |
||||
|
.clocks_container > p { |
||||
|
font-size: 20px; |
||||
|
} |
||||
|
|
||||
|
//button |
||||
|
:root { |
||||
|
--primary-light: #8abdff; |
||||
|
--primary: #6d5dfc; |
||||
|
--primary-dark: #5b0eeb; |
||||
|
--white: #FFFFFF; |
||||
|
--greyLight-1: #E4EBF5; |
||||
|
--greyLight-2: #c8d0e7; |
||||
|
--greyLight-3: #bec8e4; |
||||
|
--greyDark: #9baacf; |
||||
|
} |
||||
|
$shadow: .3rem .3rem .6rem var(--greyLight-2), |
||||
|
-.2rem -.2rem .5rem var(--white); |
||||
|
$inner-shadow: inset .2rem .2rem .5rem var(--greyLight-2), |
||||
|
inset -.2rem -.2rem .5rem var(--white); |
||||
|
|
||||
|
/* CLOCK */ |
||||
|
.clock { |
||||
|
grid-column: 2 / 3; |
||||
|
grid-row: 1 / 3; |
||||
|
width: 12rem; |
||||
|
height: 12rem; |
||||
|
justify-self: center; |
||||
|
box-shadow: $shadow; |
||||
|
border-radius: 50%; |
||||
|
display: flex; |
||||
|
justify-content: center; |
||||
|
align-items: center; |
||||
|
position: relative; |
||||
|
.hand { |
||||
|
position: absolute; |
||||
|
transform-origin: bottom; |
||||
|
bottom: 6rem; |
||||
|
border-radius: .2rem; |
||||
|
z-index: 200; |
||||
|
} |
||||
|
.hours { |
||||
|
width: .4rem; |
||||
|
height: 3.2rem; |
||||
|
background: var(--greyLight-3); |
||||
|
|
||||
|
} |
||||
|
.minutes { |
||||
|
width: .4rem; |
||||
|
height: 4.6rem; |
||||
|
background: var(--greyDark); |
||||
|
} |
||||
|
.seconds { |
||||
|
width: .2rem; |
||||
|
height: 5.2rem; |
||||
|
background: var(--primary); |
||||
|
} |
||||
|
.point { |
||||
|
position: absolute; |
||||
|
width: .8rem; |
||||
|
height: .8rem; |
||||
|
border-radius: 50%; |
||||
|
background: var(--primary); |
||||
|
z-index: 300; |
||||
|
} |
||||
|
.in-border { |
||||
|
width: 95%; |
||||
|
height: 95%; |
||||
|
border-radius: 50%; |
||||
|
display: flex; |
||||
|
position: relative; |
||||
|
box-shadow: $inner-shadow; |
||||
|
.center { |
||||
|
width: 60%; |
||||
|
height: 60%; |
||||
|
position: absolute; |
||||
|
box-shadow: inset 1px 1px 1px var(--greyLight-2), |
||||
|
inset -1px -1px 1px var(--white); |
||||
|
border-radius: 50%; |
||||
|
top: 20%; |
||||
|
left: 20%; |
||||
|
filter: blur(1px); |
||||
|
} |
||||
|
div.digit { |
||||
|
position: absolute; |
||||
|
inset: 1px; |
||||
|
text-align: center; |
||||
|
transform: rotate(calc(var(--i) * (360deg / 12))); |
||||
|
span { |
||||
|
display: inline-block; |
||||
|
font-size: 80%; |
||||
|
font-weight: 600; |
||||
|
transform: rotate(calc(var(--i) * (-360deg / 12))); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
.night-clock { |
||||
|
background-color: black; |
||||
|
color: white; |
||||
|
} |
||||
|
.no_clocks_span { |
||||
|
font-size: 16px; |
||||
|
font-weight: 500; |
||||
|
color: #714b67; |
||||
|
text-align: center; |
||||
|
background-color: #f2f2f2; |
||||
|
padding: 10px; |
||||
|
border-radius: 5px; |
||||
|
display: inline-block; |
||||
|
margin-top: -17px; |
||||
|
} |